home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume26 / veos-2.0 / part13 < prev    next >
Encoding:
Text File  |  1993-04-25  |  74.2 KB  |  2,483 lines

  1. Newsgroups: comp.sources.unix
  2. From: voodoo@hitl.washington.edu (Geoffery Coco)
  3. Subject: v26i196: veos-2.0 - The Virtual Environment Operating Shell, V2.0, Part13/16
  4. Sender: unix-sources-moderator@vix.com
  5. Approved: paul@vix.com
  6.  
  7. Submitted-By: voodoo@hitl.washington.edu (Geoffery Coco)
  8. Posting-Number: Volume 26, Issue 196
  9. Archive-Name: veos-2.0/part13
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 13 (of 16)."
  18. # Contents:  kernel_private/src/nancy/nancy_fundamental.c
  19. #   src/xlisp/xcore/doc/internals.doc
  20. # Wrapped by vixie@efficacy.home.vix.com on Sun Apr 25 23:10:45 1993
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'kernel_private/src/nancy/nancy_fundamental.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'kernel_private/src/nancy/nancy_fundamental.c'\"
  24. else
  25. echo shar: Extracting \"'kernel_private/src/nancy/nancy_fundamental.c'\" \(31245 characters\)
  26. sed "s/^X//" >'kernel_private/src/nancy/nancy_fundamental.c' <<'END_OF_FILE'
  27. X/****************************************************************************************
  28. X *                                            *
  29. X * file: nancy.c                                    *
  30. X *                                            *
  31. X * August 21, 1990: the world(s)' interface to grouples.                       *
  32. X *                                            *
  33. X * by Geoffrey P. Coco at the HITLab, Seattle.                          *
  34. X *                                            *
  35. X ****************************************************************************************/
  36. X
  37. X/****************************************************************************************
  38. X * Copyright (C) 1992  Geoffrey P. Coco, Human Interface Technology Lab, Seattle    *
  39. X ****************************************************************************************/
  40. X
  41. X
  42. X/****************************************************************************************
  43. X *                          includes galore                    */
  44. X
  45. X#include "kernel.h"
  46. X#include <string.h>
  47. X#include <malloc.h>
  48. X#include <varargs.h>
  49. X
  50. X/****************************************************************************************/
  51. X
  52. X
  53. X/****************************************************************************************
  54. X *                     forward function declarations                */
  55. X
  56. X
  57. X/* nancy setup and preprocessing */
  58. X
  59. XTVeosErr Nancy_Init();
  60. X
  61. X
  62. X/* fundamental grouple data structure utils */
  63. X
  64. XTVeosErr Nancy_NewGrouple();                         
  65. XTVeosErr Nancy_DisposeGrouple();
  66. XTVeosErr Nancy_CopyGrouple();
  67. XTVeosErr Nancy_CreateElement();
  68. XTVeosErr Nancy_DisposeElement();
  69. XTVeosErr Nancy_CopyElement();
  70. XTVeosErr Nancy_NewElementsInGrouple();
  71. XTVeosErr Nancy_DeleteElementsInGrouple();
  72. X
  73. X
  74. X/* related public nancy utils */
  75. X
  76. XTVeosErr Nancy_GroupleToStream();
  77. XTVeosErr Nancy_ElementToStream();
  78. XTVeosErr Nancy_GroupleToStreamWithLevel();
  79. XTVeosErr Nancy_ElementToStreamWithLevel();
  80. X
  81. XTVeosErr Nancy_EmptyGrouple();
  82. XTVeosErr Nancy_InsertEltList();
  83. XTVeosErr Nancy_CopyEltList();
  84. XTVeosErr Nancy_ConcatGrouple();
  85. X
  86. XTVeosErr Nancy_GetFileSize();
  87. XTVeosErr Nancy_FileToGrouple();
  88. XTVeosErr Nancy_TrapErr();
  89. X
  90. X
  91. X/* private nancy utils */
  92. X
  93. XTVeosErr Nancy_ResizeEltList();
  94. XTVeosErr Nancy_SetupTypeSizes();
  95. X
  96. X/****************************************************************************************/
  97. X
  98. X
  99. X
  100. X
  101. X/****************************************************************************************
  102. X *                setup and preprocessing                    *
  103. X ****************************************************************************************/
  104. X
  105. X
  106. X/****************************************************************************************
  107. X * Nancy_Init                                    */
  108. X
  109. XTVeosErr Nancy_Init()
  110. X{
  111. X    TVeosErr        iSuccess;
  112. X
  113. X    iSuccess = VEOS_MEM_ERR;
  114. X    LINE_COUNT = 0;
  115. X    NANCY_MINTIME = 0;
  116. X    NANCY_TIME = 1;
  117. X
  118. X    /** setup runtime hash table for element sizes **/
  119. X
  120. X    iSuccess = Nancy_SetupFastMem();
  121. X    if (iSuccess == VEOS_SUCCESS) {
  122. X    
  123. X    /** StreamToElement assumes global buffer **/
  124. X    
  125. X    if (NEWPTR(NANCY_BUF, char *, VEOS_GROUPLE_BUF_SIZE)) {
  126. X        
  127. X        NIL_ELT.iType = GR_unspecified;
  128. X        NIL_ELT.u.pU = nil;
  129. X        NIL_ELT.tLastMod = 0x7FFFFFFF;
  130. X        NIL_ELT.iFlags = 0;
  131. X
  132. X        iSuccess = Nancy_NewGrouple(&GR_INSPACE);
  133. X        if (iSuccess == VEOS_SUCCESS) {
  134. X
  135. X        iSuccess = Nancy_NewGrouple(&WORK_SPACE);
  136. X        }
  137. X        }
  138. X    }
  139. X    
  140. X    return(iSuccess);
  141. X
  142. X    } /* Nancy_Init */
  143. X/****************************************************************************************/
  144. X
  145. X
  146. X
  147. X/****************************************************************************************
  148. X *             fundamental nancy data structure utils                *
  149. X ****************************************************************************************/
  150. X
  151. X
  152. X
  153. X/****************************************************************************************
  154. X * Nancy_NewGrouple                                    */
  155. X
  156. XTVeosErr Nancy_NewGrouple(hDestGrouple)
  157. X    THGrouple        hDestGrouple;
  158. X{
  159. X    TVeosErr        iSuccess;
  160. X    TPGrouple        pNewGrouple;
  161. X
  162. X
  163. X    iSuccess = VEOS_FAILURE;                       /* pessimism */
  164. X
  165. X
  166. X    if (hDestGrouple) {                    /* sanity check */
  167. X
  168. X    iSuccess = VEOS_MEM_ERR;            /* more pessimism */
  169. X
  170. X    *hDestGrouple = (TPGrouple) nil; 
  171. X
  172. X
  173. X
  174. X    /** allocate the grouple structure itself **/
  175. X
  176. X    iSuccess = Shell_NewBlock(TYPE_SIZES[GR_grouple], &pNewGrouple,
  177. X                  "grouple");
  178. X
  179. X    if (iSuccess == VEOS_SUCCESS) {
  180. X        pNewGrouple->pEltList = nil;
  181. X        pNewGrouple->iElts = 0;
  182. X        pNewGrouple->iFlags = 0;
  183. X
  184. X        *hDestGrouple = pNewGrouple;
  185. X        }
  186. X    }
  187. X
  188. X    return(iSuccess);
  189. X
  190. X    } /* Nancy_NewGrouple */
  191. X/****************************************************************************************/
  192. X
  193. X
  194. X
  195. X
  196. X/****************************************************************************************
  197. X * Nancy_DisposeGrouple                                    */
  198. X
  199. XTVeosErr Nancy_DisposeGrouple(pDeadGrouple)
  200. X    TPGrouple        pDeadGrouple;
  201. X{
  202. X    TVeosErr        iSuccess;
  203. X    int            iEltIndex;
  204. X    TPElt        pEltList;
  205. X
  206. X    iSuccess = VEOS_SUCCESS;            /* what could go wrong? */
  207. X
  208. X    if (pDeadGrouple) {                /* sanity check */
  209. X
  210. X
  211. X    /** clear all elements from grouple **/
  212. X
  213. X    Nancy_DeleteElementsInGrouple(pDeadGrouple, 0, pDeadGrouple->iElts);
  214. X        
  215. X
  216. X    /** deallocate element list itself **/
  217. X
  218. X    Nancy_ResizeEltList(pDeadGrouple, 0);
  219. X
  220. X
  221. X    /** deallocate the grouple structure itself **/
  222. X
  223. X    Shell_ReturnBlock(pDeadGrouple, TYPE_SIZES[GR_grouple], "grouple");
  224. X    }
  225. X
  226. X
  227. X    return(iSuccess);
  228. X
  229. X    } /* Nancy_DisposeGrouple */
  230. X/****************************************************************************************/
  231. X
  232. X
  233. X
  234. X
  235. X/****************************************************************************************
  236. X * Nancy_CopyGrouple                                    */
  237. XTVeosErr Nancy_CopyGrouple(pSrcGrouple, pDestGrouple)
  238. X    TPGrouple        pSrcGrouple;
  239. X    TPGrouple        pDestGrouple;
  240. X{
  241. X    TVeosErr        iSuccess;
  242. X
  243. X    iSuccess = VEOS_FAILURE;                          /* pessimism */
  244. X
  245. X    if (pSrcGrouple && pDestGrouple) {                /* sanity check */
  246. X
  247. X    /** allocate element list enough for all copied elements **/
  248. X
  249. X    iSuccess = Nancy_ResizeEltList(pDestGrouple, pSrcGrouple->iElts);
  250. X    if (iSuccess == VEOS_SUCCESS) {
  251. X
  252. X
  253. X        iSuccess = Nancy_CopyEltList(pSrcGrouple->pEltList,
  254. X                     pDestGrouple->pEltList,
  255. X                     pSrcGrouple->iElts);
  256. X        }
  257. X    }
  258. X
  259. X    return(iSuccess);
  260. X
  261. X    } /* Nancy_CopyGrouple */
  262. X/****************************************************************************************/
  263. X
  264. X
  265. X
  266. X
  267. X/****************************************************************************************
  268. X * Nancy_CreateElement                                    */
  269. X
  270. XTVeosErr Nancy_CreateElement(pDestElt, iType, iSize)
  271. X    TPElt        pDestElt;
  272. X    int            iType, iSize;
  273. X{
  274. X    TVeosErr        iSuccess;
  275. X    str15        sTypeName;
  276. X
  277. X    iSuccess = VEOS_FAILURE;
  278. X
  279. X    if (pDestElt) {        /* sane? */
  280. X
  281. X    pDestElt->iType = iType;
  282. X
  283. X    iSuccess = VEOS_MEM_ERR;
  284. X
  285. X    switch (iType) {
  286. X
  287. X    case GR_grouple:
  288. X        iSuccess = Nancy_NewGrouple(&pDestElt->u.pGr);
  289. X        break;
  290. X
  291. X    case GR_vector:
  292. X        iSuccess = Nancy_NewGrouple(&pDestElt->u.pGr);
  293. X        pDestElt->iType = GR_vector;
  294. X        break;
  295. X
  296. X    case GR_string:
  297. X    case GR_prim:
  298. X        if (iSize > 0) {
  299. X        if (NEWPTR(pDestElt->u.pS, char *, iSize))
  300. X            iSuccess = VEOS_SUCCESS;
  301. X        }
  302. X        else {
  303. X        pDestElt->u.pS = nil;
  304. X        iSuccess = VEOS_SUCCESS;
  305. X        }
  306. X        break;
  307. X
  308. X    case GR_float:    
  309. X    case GR_int:
  310. X    case GR_these:
  311. X    case GR_theseall:
  312. X    case GR_some:
  313. X    case GR_any:
  314. X    case GR_here:
  315. X        /* nothing to allocate */
  316. X        iSuccess = VEOS_SUCCESS;
  317. X        break;
  318. X
  319. X    case GR_unspecified:
  320. X    default:
  321. X        pDestElt->u.pU = nil;
  322. X        iSuccess = VEOS_SUCCESS;
  323. X        break;
  324. X
  325. X        } /* switch */
  326. X    }
  327. X
  328. X    return(iSuccess);
  329. X
  330. X    } /* Nancy_CreateElement */
  331. X/****************************************************************************************/
  332. X
  333. X
  334. X
  335. X
  336. X
  337. X/****************************************************************************************
  338. X * Nancy_DisposeElement                                    */
  339. X
  340. XTVeosErr Nancy_DisposeElement(pDestElt)
  341. X    TPElt        pDestElt;
  342. X{
  343. X    TVeosErr        iSuccess;
  344. X    str15        sTypeName;
  345. X
  346. X    iSuccess = VEOS_FAILURE;
  347. X
  348. X    if (pDestElt) {
  349. X    
  350. X    /** recurs to sublist if necessary **/
  351. X    switch (pDestElt->iType) {
  352. X        
  353. X    case GR_grouple:
  354. X    case GR_vector:
  355. X        Nancy_DisposeGrouple(pDestElt->u.pGr);
  356. X        break;
  357. X        
  358. X    case GR_string:
  359. X        DUMP(pDestElt->u.pS);
  360. X        break;
  361. X        
  362. X    case GR_float:    
  363. X    case GR_int:
  364. X    case GR_these:
  365. X    case GR_theseall:
  366. X    case GR_some:
  367. X    case GR_any:
  368. X    case GR_here:
  369. X    case GR_unspecified:
  370. X    default:
  371. X        /* nothing allocated */
  372. X        break;
  373. X        
  374. X        } /* switch */
  375. X    
  376. X    *pDestElt = NIL_ELT;
  377. X    
  378. X    iSuccess = VEOS_SUCCESS;
  379. X    }
  380. X
  381. X    return(iSuccess);
  382. X
  383. X    } /* Nancy_DisposeElement */
  384. X/****************************************************************************************/
  385. X
  386. X
  387. X
  388. X
  389. X/****************************************************************************************
  390. X * Nancy_CopyElement                                    */
  391. X
  392. XTVeosErr Nancy_CopyElement(pSrcElt, pDestElt)
  393. X    TPElt        pSrcElt, pDestElt;
  394. X{
  395. X    TVeosErr        iSuccess;
  396. X
  397. X    iSuccess = VEOS_FAILURE;
  398. X
  399. X    if (pSrcElt && pDestElt && pSrcElt->iType == pDestElt->iType) {    /* sane? */
  400. X
  401. X    iSuccess = VEOS_SUCCESS;
  402. X
  403. X    switch (pSrcElt->iType) {
  404. X
  405. X    case GR_grouple:
  406. X    case GR_vector:
  407. X        iSuccess = Nancy_CopyGrouple(pSrcElt->u.pGr,
  408. X                     pDestElt->u.pGr);
  409. X        break;
  410. X
  411. X    case GR_float:    
  412. X    case GR_int:
  413. X    case GR_these:
  414. X    case GR_some:
  415. X        pDestElt->u.iVal = pSrcElt->u.iVal;
  416. X        break;
  417. X
  418. X    case GR_theseall:
  419. X    case GR_any:
  420. X    case GR_here:
  421. X        /** no data to copy **/
  422. X        break;
  423. X
  424. X    case GR_string:
  425. X    case GR_prim:
  426. X        if (pDestElt->u.pS)
  427. X        strcpy(pDestElt->u.pS, pSrcElt->u.pS);
  428. X        else
  429. X        pDestElt->u.pS = strdup(pSrcElt->u.pS);
  430. X        break;
  431. X
  432. X    case GR_unspecified:
  433. X        break;
  434. X
  435. X        } /* switch */
  436. X
  437. X    pDestElt->tLastMod = pSrcElt->tLastMod;
  438. X    }
  439. X
  440. X    return(iSuccess);
  441. X
  442. X    } /* Nancy_CopyElement */
  443. X/****************************************************************************************/
  444. X
  445. X
  446. X
  447. X
  448. X/****************************************************************************************
  449. X * Nancy_NewElementsInGrouple                                */
  450. X
  451. XTVeosErr Nancy_NewElementsInGrouple(pDestGrouple, iInsertElt, iElts, iType, iSize)
  452. X    TPGrouple        pDestGrouple;
  453. X    int            iInsertElt, iElts, iType, iSize;
  454. X{
  455. X    TVeosErr        iSuccess;
  456. X    TPElt        pEltList;
  457. X    int            iIndex, iOldElts, iLimit;
  458. X
  459. X    iSuccess = VEOS_FAILURE;
  460. X
  461. X    if (pDestGrouple) {
  462. X
  463. X    iOldElts = pDestGrouple->iElts;        /* ResizeEltList() clobbers this field */
  464. X
  465. X    iSuccess = Nancy_ResizeEltList(pDestGrouple,
  466. X                       iOldElts > iInsertElt ?
  467. X                       (iOldElts + iElts) : (iInsertElt + iElts));
  468. X    if (iSuccess == VEOS_SUCCESS) {
  469. X
  470. X
  471. X
  472. X        /** use stack var for speed **/
  473. X
  474. X        pEltList = pDestGrouple->pEltList;
  475. X
  476. X
  477. X
  478. X        /** all elements which occur after insertion point are shifted down **/
  479. X
  480. X        iIndex = iOldElts + iElts - 1;            
  481. X        iLimit = iInsertElt + iElts;
  482. X
  483. X        while (iIndex >= iLimit) {
  484. X
  485. X        pEltList[iIndex] = pEltList[iIndex - iElts];
  486. X
  487. X        iIndex --;
  488. X        }
  489. X
  490. X
  491. X        /** initialize new elements that may have been created by list growth **/
  492. X
  493. X        iIndex = iOldElts;
  494. X        iLimit = iInsertElt + iElts;
  495. X
  496. X        while (iIndex < iLimit) {
  497. X
  498. X        pEltList[iIndex] = NIL_ELT;
  499. X
  500. X        iIndex ++;
  501. X        }
  502. X
  503. X
  504. X        /** attempt to create actual element data block, if requested **/
  505. X
  506. X        iIndex = iInsertElt;
  507. X        iLimit = iInsertElt + iElts;
  508. X        while (iIndex < iLimit && iSuccess == VEOS_SUCCESS) {
  509. X
  510. X        iSuccess = Nancy_CreateElement(&pEltList[iIndex], iType, iSize);
  511. X
  512. X        iIndex ++;
  513. X        }
  514. X        }
  515. X    }
  516. X
  517. X    return(iSuccess);
  518. X
  519. X    } /* Nancy_NewElementsInGrouple */
  520. X/****************************************************************************************/
  521. X
  522. X
  523. X
  524. X
  525. X/****************************************************************************************
  526. X * Nancy_DeleteElementsInGrouple                            */
  527. X
  528. XTVeosErr Nancy_DeleteElementsInGrouple(pGrouple, iStartElt, iElts)
  529. X    TPGrouple        pGrouple;
  530. X    int            iStartElt, iElts;
  531. X{
  532. X    TVeosErr        iSuccess;
  533. X    int            iIndex, iEndElt, iNewElts;
  534. X    TPElt        pEltList;
  535. X
  536. X    iSuccess = VEOS_SUCCESS;
  537. X    iEndElt = iStartElt + iElts;
  538. X
  539. X    if (pGrouple &&
  540. X    iElts > 0) {
  541. X
  542. X    if (pGrouple->iElts >= iEndElt) {        /* sane? */
  543. X        
  544. X        
  545. X        /** deallocate specific element data **/
  546. X        
  547. X        iIndex = iStartElt;
  548. X        while (iIndex < iEndElt) {
  549. X        
  550. X        Nancy_DisposeElement(&pGrouple->pEltList[iIndex]);
  551. X        
  552. X        iIndex ++;
  553. X        }    
  554. X        
  555. X        
  556. X        iSuccess = Nancy_DownShift(pGrouple, iStartElt, iElts);
  557. X        }
  558. X    }
  559. X
  560. X    return(iSuccess);
  561. X
  562. X    } /* Nancy_DeleteElementsInGrouple */
  563. X/****************************************************************************************/
  564. X
  565. X
  566. X/****************************************************************************************
  567. X                     Data Conversion
  568. X ****************************************************************************************/
  569. X
  570. X
  571. X/****************************************************************************************
  572. X * Nancy_ElementToStream                                */
  573. X
  574. XTVeosErr Nancy_ElementToStream(pElt, pStream)
  575. X    TPElt        pElt;
  576. X    FILE        *pStream;
  577. X{
  578. X    TVeosErr        iSuccess;
  579. X    FILE        *pSave;
  580. X
  581. X    iSuccess = VEOS_FAILURE;
  582. X
  583. X    if (pElt && pStream) {                /* sane? */
  584. X
  585. X    pSave = GR_STREAM;
  586. X    GR_STREAM = pStream;
  587. X
  588. X    iSuccess = Nancy_ElementToStreamAux(pElt, 0);
  589. X
  590. X    GR_STREAM = pSave;
  591. X    }
  592. X
  593. X    return(iSuccess);
  594. X
  595. X    } /* Nancy_ElementToStream */
  596. X/****************************************************************************************/
  597. X
  598. X
  599. X
  600. X
  601. X/****************************************************************************************
  602. X * Nancy_GroupleToStream                                */
  603. X
  604. XTVeosErr Nancy_GroupleToStream(pGrouple, pStream)
  605. X    TPGrouple        pGrouple;
  606. X    FILE        *pStream;
  607. X{
  608. X    TElt        elt;
  609. X    TVeosErr        iSuccess;
  610. X
  611. X    iSuccess = VEOS_FAILURE;
  612. X
  613. X    if (pGrouple && pStream) {                /* sane? */
  614. X
  615. X    elt = NIL_ELT;
  616. X    elt.iType = GR_grouple;
  617. X    elt.u.pGr = pGrouple;
  618. X    
  619. X    iSuccess = Nancy_ElementToStream(&elt, pStream);
  620. X    }
  621. X
  622. X    return(iSuccess);
  623. X
  624. X    } /* Nancy_GroupleToStream */
  625. X/****************************************************************************************/
  626. X
  627. X
  628. X
  629. X
  630. X/****************************************************************************************
  631. X * Nancy_ElementToStreamWithLevel                            */
  632. X
  633. XTVeosErr Nancy_ElementToStreamWithLevel(pElt, pStream, iLevel)
  634. X    TPElt        pElt;
  635. X    FILE        *pStream;
  636. X    int            iLevel;
  637. X{
  638. X    TVeosErr        iSuccess;
  639. X    FILE        *pSave;
  640. X
  641. X    iSuccess = VEOS_FAILURE;
  642. X
  643. X    if (pElt && pStream) {                /* sane? */
  644. X
  645. X    pSave = GR_STREAM;
  646. X    GR_STREAM = pStream;
  647. X
  648. X    iSuccess = Nancy_ElementToStreamAux(pElt, iLevel);
  649. X
  650. X    GR_STREAM = pSave;
  651. X    }
  652. X
  653. X    return(iSuccess);
  654. X
  655. X    } /* Nancy_ElementToStreamWithLevel */
  656. X/****************************************************************************************/
  657. X
  658. X
  659. X
  660. X
  661. X/****************************************************************************************
  662. X * Nancy_GroupleToStreamWithLevel                            */
  663. X
  664. XTVeosErr Nancy_GroupleToStreamWithLevel(pGrouple, pStream, iLevel)
  665. X    TPGrouple        pGrouple;
  666. X    FILE        *pStream;
  667. X    int            iLevel;
  668. X{
  669. X    TElt        elt;
  670. X    TVeosErr        iSuccess;
  671. X
  672. X    iSuccess = VEOS_FAILURE;
  673. X
  674. X    if (pGrouple && pStream) {                /* sane? */
  675. X
  676. X    elt = NIL_ELT;
  677. X    elt.iType = GR_grouple;
  678. X    elt.u.pGr = pGrouple;
  679. X
  680. X    iSuccess = Nancy_ElementToStreamWithLevel(&elt, pStream, iLevel);
  681. X    }
  682. X
  683. X    return(iSuccess);
  684. X
  685. X    } /* Nancy_GroupleToStreamWithLevel */
  686. X/****************************************************************************************/
  687. X
  688. X
  689. X
  690. X
  691. X/****************************************************************************************
  692. X                   Grouple -> Network Message
  693. X ****************************************************************************************/
  694. X
  695. X
  696. X/****************************************************************************************
  697. X * Nancy_EltToMessage                                    */
  698. X
  699. XTVeosErr Nancy_EltToMessage(pElt, pBuffer, pLen)
  700. X    TPElt        pElt;
  701. X    char        *pBuffer;
  702. X    int            *pLen;
  703. X{
  704. X    int            iLen, iType;
  705. X
  706. X    if (pElt) {                /* sane? */
  707. X
  708. X    iType = pElt->iType;
  709. X
  710. X    /** first part of message element is element type **/
  711. X    /** assume pBuffer is aligned **/
  712. X
  713. X    *(int *) pBuffer = htonl(iType);    
  714. X
  715. X    pBuffer += 4;
  716. X    *pLen += 4;
  717. X
  718. X    switch (iType) {
  719. X
  720. X    case GR_grouple:
  721. X    case GR_vector:
  722. X        iLen = 0;
  723. X        Nancy_GroupleToMessage(pElt->u.pGr, pBuffer, &iLen);
  724. X        break;
  725. X
  726. X    case GR_int:
  727. X    case GR_float:
  728. X        *(long *) pBuffer = htonl(pElt->u.iVal);
  729. X        iLen = 4;
  730. X        break;
  731. X
  732. X    case GR_string:
  733. X    case GR_prim:
  734. X        strcpy(pBuffer, pElt->u.pS);
  735. X        iLen = MEMSIZE(strlen(pElt->u.pS) + 1);
  736. X        break;
  737. X        
  738. X    case GR_unspecified:
  739. X    default:
  740. X        iLen = 0;
  741. X        break;
  742. X        
  743. X        } /* switch */
  744. X
  745. X    *pLen += iLen;
  746. X    }
  747. X
  748. X    return(VEOS_SUCCESS);
  749. X
  750. X    } /* Nancy_EltToMessage */
  751. X/****************************************************************************************/
  752. X
  753. X
  754. X
  755. X/****************************************************************************************
  756. X * Nancy_GroupleToMessage                                */
  757. X
  758. XTVeosErr Nancy_GroupleToMessage(pGrouple, pBuffer, pLen)
  759. X    TPGrouple        pGrouple;
  760. X    char        *pBuffer;
  761. X    int            *pLen;
  762. X{
  763. X    int            iEltIndex, iElts, iLen;
  764. X    TPElt        pEltList;
  765. X    
  766. X    if (pGrouple) {                /* sane? */
  767. X
  768. X
  769. X    /** use stack vars for speed **/
  770. X
  771. X    iElts = pGrouple->iElts;
  772. X    pEltList = pGrouple->pEltList;
  773. X
  774. X
  775. X
  776. X    /** first code of protocol is number of elements **/
  777. X
  778. X    *(int *) pBuffer = htonl(iElts);    /** assume pBuffer is aligned **/
  779. X
  780. X    pBuffer += 4;
  781. X    *pLen += 4;
  782. X
  783. X
  784. X    for (iEltIndex = 0; iEltIndex < iElts; iEltIndex ++) {
  785. X        
  786. X        iLen = 0;
  787. X
  788. X        /** invoke recursive translation **/
  789. X
  790. X        Nancy_EltToMessage(&pEltList[iEltIndex], pBuffer, &iLen);
  791. X
  792. X        pBuffer += iLen;
  793. X        *pLen += iLen;
  794. X        }
  795. X    }
  796. X
  797. X    return(VEOS_SUCCESS);
  798. X
  799. X    } /* Nancy_GroupleToMessage */
  800. X/****************************************************************************************/
  801. X
  802. X
  803. X
  804. X
  805. X/****************************************************************************************
  806. X *                related public utils                    *
  807. X ****************************************************************************************/
  808. X
  809. X
  810. X/****************************************************************************************
  811. X * Nancy_EmptyGrouple                                    */
  812. X
  813. XTVeosErr Nancy_EmptyGrouple(pGrouple)
  814. X    TPGrouple        pGrouple;
  815. X{
  816. X    TVeosErr        iSuccess;
  817. X
  818. X    iSuccess = VEOS_FAILURE;
  819. X
  820. X    if (pGrouple && pGrouple->iElts > 0) {
  821. X
  822. X    iSuccess = Nancy_DeleteElementsInGrouple(pGrouple, 0, pGrouple->iElts);
  823. X    }
  824. X
  825. X    return(iSuccess);
  826. X
  827. X    } /* Nancy_EmptyGrouple */
  828. X/****************************************************************************************/
  829. X
  830. X
  831. X
  832. X
  833. X/****************************************************************************************/
  834. XTVeosErr Nancy_InsertEltList(pSrcList, iSrcElts, pDestGrouple, iStartElt)
  835. X    TPElt        pSrcList;
  836. X    int            iSrcElts, iStartElt;
  837. X    TPGrouple        pDestGrouple;
  838. X{
  839. X    TVeosErr        iSuccess;
  840. X    int            iSrcIndex;
  841. X    TPElt        pDestList;
  842. X
  843. X
  844. X    iSuccess = VEOS_SUCCESS;
  845. X
  846. X    if (pSrcList && pDestGrouple) {        /* sane? */
  847. X    
  848. X    iSuccess = Nancy_NewElementsInGrouple(pDestGrouple,
  849. X                          iStartElt,
  850. X                          iSrcElts,
  851. X                          GR_unspecified, 0);
  852. X    if (iSuccess == VEOS_SUCCESS) {
  853. X
  854. X
  855. X        /** transfer each element from chosen starting locations **/
  856. X        
  857. X        pDestList = &pDestGrouple->pEltList[iStartElt];
  858. X        iSrcIndex = 0;
  859. X        while (iSrcIndex < iSrcElts) {
  860. X        
  861. X        pDestList[iSrcIndex] = pSrcList[iSrcIndex];
  862. X        
  863. X
  864. X        /** set default vals for src elements **/
  865. X        /** in case the caller disposes the src elt list after the call **/
  866. X        
  867. X        pSrcList[iSrcIndex++] = NIL_ELT;
  868. X        }
  869. X        }
  870. X    }
  871. X
  872. X    return(iSuccess);
  873. X
  874. X    } /* Nancy_InsertEltList */
  875. X/****************************************************************************************/
  876. X
  877. X
  878. X
  879. X
  880. X/****************************************************************************************/
  881. XTVeosErr Nancy_CopyEltList(pSrcList, pDestList, iElts)
  882. X    TPElt        pSrcList, pDestList;
  883. X    int            iElts;
  884. X{
  885. X    int            iEltIndex;
  886. X    TVeosErr        iSuccess = VEOS_SUCCESS;
  887. X
  888. X
  889. X    if (pSrcList && pDestList) {        /* sane? */
  890. X
  891. X    /** copy the grouple element list, one elt at a time **/
  892. X    
  893. X    iSuccess = VEOS_SUCCESS;
  894. X    iEltIndex = 0;
  895. X    while (iEltIndex < iElts && iSuccess == VEOS_SUCCESS) {
  896. X
  897. X        pDestList[iEltIndex] = pSrcList[iEltIndex];
  898. X
  899. X        if (pSrcList[iEltIndex].iType != GR_unspecified) {
  900. X
  901. X        iSuccess = Nancy_CreateElement(&pDestList[iEltIndex],
  902. X                           pSrcList[iEltIndex].iType, 0);
  903. X        if (iSuccess == VEOS_SUCCESS)
  904. X            
  905. X            iSuccess = Nancy_CopyElement(&pSrcList[iEltIndex],
  906. X                         &pDestList[iEltIndex]);
  907. X        }
  908. X        
  909. X        iEltIndex ++;
  910. X        }
  911. X    }
  912. X
  913. X    return(iSuccess);
  914. X    
  915. X    } /* Nancy_CopyEltList */
  916. X/****************************************************************************************/
  917. X
  918. X
  919. X
  920. X
  921. X/****************************************************************************************
  922. X * Nancy_ConcatGrouple                                    */
  923. XTVeosErr Nancy_ConcatGrouple(pSrcGrouple, pDestGrouple)
  924. X    TPGrouple        pSrcGrouple;
  925. X    TPGrouple        pDestGrouple;
  926. X{
  927. X    TVeosErr        iSuccess;
  928. X    int            iOldElts;
  929. X
  930. X    iSuccess = VEOS_FAILURE;                          /* pessimism */
  931. X
  932. X    if (pSrcGrouple && pDestGrouple) {                /* sanity check */
  933. X
  934. X
  935. X    /** allocate element list enough for all copied elements **/
  936. X
  937. X    iOldElts = pDestGrouple->iElts;
  938. X    iSuccess = Nancy_ResizeEltList(pDestGrouple,
  939. X                       iOldElts + pSrcGrouple->iElts);
  940. X    if (iSuccess == VEOS_SUCCESS) {
  941. X
  942. X
  943. X        iSuccess = Nancy_CopyEltList(pSrcGrouple->pEltList,
  944. X                     &pDestGrouple->pEltList[iOldElts],
  945. X                     pSrcGrouple->iElts);
  946. X        }
  947. X    }
  948. X
  949. X    return(iSuccess);
  950. X
  951. X    } /* Nancy_ConcatGrouple */
  952. X/****************************************************************************************/
  953. X
  954. X
  955. X
  956. X
  957. X/****************************************************************************************/
  958. XTVeosErr Nancy_EltIdentical(pLeftElt, pRightElt)
  959. X    TPElt        pRightElt, pLeftElt;
  960. X{
  961. X    TVeosErr        iSuccess;
  962. X    int            iType;
  963. X    boolean        bSame;
  964. X    char        *pGenericRight, *pGenericLeft, *pMax;
  965. X    
  966. X
  967. X    iSuccess = VEOS_FAILURE;
  968. X    bSame = FALSE;
  969. X
  970. X    if (pLeftElt == pRightElt)
  971. X    bSame = TRUE;
  972. X
  973. X    else if (pLeftElt &&
  974. X         pRightElt &&
  975. X         pLeftElt->iType == pRightElt->iType) {
  976. X
  977. X    iType = pLeftElt->iType;
  978. X    switch (iType) {
  979. X        
  980. X    case GR_float:
  981. X        if (pLeftElt->u.fVal == pRightElt->u.fVal)
  982. X        bSame = TRUE;
  983. X        break;
  984. X        
  985. X    case GR_int:
  986. X        if (pLeftElt->u.iVal == pRightElt->u.iVal)
  987. X        bSame = TRUE;
  988. X        break;
  989. X        
  990. X    case GR_string:
  991. X    case GR_prim:
  992. X        if (strcmp(pLeftElt->u.pS, pRightElt->u.pS) == 0)
  993. X        bSame = TRUE;
  994. X        break;
  995. X        
  996. X    case GR_unspecified:
  997. X    default:
  998. X        bSame = TRUE;
  999. X        break;
  1000. X        
  1001. X        } /* switch */
  1002. X    }
  1003. X    
  1004. X    if (bSame)
  1005. X    iSuccess = VEOS_SUCCESS;
  1006. X
  1007. X    return(iSuccess);
  1008. X
  1009. X    } /* Nancy_EltIdentical */
  1010. X/****************************************************************************************/
  1011. X
  1012. X
  1013. X
  1014. X
  1015. X/****************************************************************************************
  1016. X * Nancy_TrapErr                                    */
  1017. X
  1018. XTVeosErr Nancy_TrapErr(iErr)
  1019. X    TVeosErr        iErr;
  1020. X{
  1021. X    switch(iErr) {
  1022. X    
  1023. X    case NANCY_EndOfGrouple:
  1024. X    fprintf(stderr, "nancy %s: end of grouple reached\n", WHOAMI);
  1025. X    break;         
  1026. X    
  1027. X    case NANCY_MisplacedLeftBracket:
  1028. X    fprintf(stderr, "nancy %s: misplaced '[', near line: %d\n", WHOAMI, LINE_COUNT);    
  1029. X    break;
  1030. X    
  1031. X    case NANCY_MisplacedRightBracket:
  1032. X    fprintf(stderr, "nancy %s: misplaced ']', near line: %d\n", WHOAMI, LINE_COUNT);    
  1033. X    break;
  1034. X    
  1035. X    case NANCY_MissingRightBracket:
  1036. X    fprintf(stderr, "nancy %s: missing ']', near line: %d\n", WHOAMI, LINE_COUNT);    
  1037. X    break;
  1038. X    
  1039. X    case NANCY_BadType:
  1040. X    fprintf(stderr, "nancy %s: bad element type, near line: %d\n", WHOAMI, LINE_COUNT);    
  1041. X    break;
  1042. X    
  1043. X    case NANCY_NoTypeMatch:
  1044. X    fprintf(stderr, "nancy %s: unknown data type, near line: %d\n", WHOAMI, LINE_COUNT);
  1045. X    break;
  1046. X    
  1047. X    case VEOS_EOF:
  1048. X    fprintf(stderr, "nancy %s: end of stream reached permaturely, near line: %d\n", WHOAMI, LINE_COUNT);
  1049. X    break;
  1050. X    
  1051. X    case VEOS_MEM_ERR:
  1052. X    fprintf(stderr, "nancy %s: memory error\n", WHOAMI);
  1053. X    break;
  1054. X    
  1055. X    case VEOS_FAILURE:
  1056. X    fprintf(stderr, "nancy %s: bad parameters\n", WHOAMI);
  1057. X    break;
  1058. X    
  1059. X    case VEOS_SUCCESS:
  1060. X    fprintf(stderr, "nancy %s: success\n", WHOAMI);
  1061. X    break;
  1062. X    
  1063. X    case NANCY_NoMatch:
  1064. X    fprintf(stderr, "nancy %s: no matches were found\n", WHOAMI);
  1065. X    break;
  1066. X
  1067. X    case NANCY_NotSupported:
  1068. X    fprintf(stderr, "nancy %s: that operation not currently supported\n", WHOAMI);
  1069. X    break;
  1070. X    
  1071. X    case NANCY_SrcTooShort:
  1072. X    fprintf(stderr, "nancy %s: no match - source grouple shorter than pattern\n", WHOAMI);
  1073. X    break;
  1074. X
  1075. X    case NANCY_PatTooShort:
  1076. X    fprintf(stderr, "nancy %s: no match - pattern shorter than source grouple\n", WHOAMI);
  1077. X    break;
  1078. X
  1079. X    default:
  1080. X    fprintf(stderr, "nancy %s: unknown error: %d\n", WHOAMI, iErr);
  1081. X    break;
  1082. X    
  1083. X    } /* switch */
  1084. X    
  1085. X    } /* Nancy_TrapErr */
  1086. X/****************************************************************************************/
  1087. X
  1088. X
  1089. X
  1090. X/****************************************************************************************
  1091. X *                       private routines                    *
  1092. X ****************************************************************************************/
  1093. X
  1094. X
  1095. X/****************************************************************************************
  1096. X * Nancy_ResizeEltList                                    */
  1097. X
  1098. XTVeosErr Nancy_ResizeEltList(pDestGrouple, iNewElts)
  1099. X    TPGrouple        pDestGrouple;
  1100. X    int            iNewElts;
  1101. X{        
  1102. X    TVeosErr        iSuccess;
  1103. X    TPElt        pEltList;
  1104. X    int            iIsLen, iShouldLen;
  1105. X
  1106. X    iSuccess = VEOS_SUCCESS;    
  1107. X
  1108. X    if (pDestGrouple) {                /* sane? */
  1109. X
  1110. X
  1111. X    /** if element ptr array is too long or too short, alter size **/
  1112. X
  1113. X    iShouldLen = ELTS_ALLOCATED(iNewElts);
  1114. X    iIsLen = ELTS_ALLOCATED(pDestGrouple->iElts);
  1115. X
  1116. X    if (iShouldLen != iIsLen) {
  1117. X
  1118. X        iSuccess = VEOS_MEM_ERR;
  1119. X        pEltList = nil;
  1120. X
  1121. X
  1122. X        /**---------------------------------------------------**/
  1123. X        /** use fast in-house memory scheme for element lists **/
  1124. X        /**---------------------------------------------------**/
  1125. X        
  1126. X        if (iShouldLen <= 0) {
  1127. X        
  1128. X        /** want to dispose all elt list memory **/
  1129. X        
  1130. X        if (pDestGrouple->pEltList)
  1131. X            Shell_ReturnBlock(pDestGrouple->pEltList,
  1132. X                      iIsLen * sizeof(TElt), "elt list");
  1133. X        }
  1134. X        
  1135. X        else if (pDestGrouple->pEltList) {
  1136. X        
  1137. X        
  1138. X        /** want to resize elt list array **/
  1139. X        
  1140. X        iSuccess = Shell_NewBlock(iShouldLen * sizeof(TElt),
  1141. X                      &pEltList, "bigger elt list");
  1142. X        if (iSuccess == VEOS_SUCCESS) {
  1143. X            
  1144. X            bcopy(pDestGrouple->pEltList,
  1145. X              pEltList,
  1146. X              (iIsLen < iShouldLen ? iIsLen : iShouldLen) * sizeof(TElt));
  1147. X            
  1148. X            Shell_ReturnBlock(pDestGrouple->pEltList,
  1149. X                      iIsLen * sizeof(TElt), "smaller elt list");
  1150. X            }
  1151. X        }
  1152. X        
  1153. X        
  1154. X        else {
  1155. X        /** want to create elt list for first time **/
  1156. X        
  1157. X        iSuccess = Shell_NewBlock(iShouldLen * sizeof(TElt),
  1158. X                      &pEltList, "elt list");
  1159. X        }
  1160. X
  1161. X        /** attach new element array (contains old contents) **/
  1162. X
  1163. X        if (iSuccess = VEOS_SUCCESS)
  1164. X        pDestGrouple->pEltList = pEltList;
  1165. X        }
  1166. X
  1167. X    pDestGrouple->iElts = iNewElts;
  1168. X    }
  1169. X
  1170. X    return(iSuccess);
  1171. X
  1172. X    } /* Nancy_ResizeEltList */
  1173. X/****************************************************************************************/
  1174. X
  1175. X
  1176. X
  1177. X/****************************************************************************************/
  1178. XTVeosErr Nancy_DownShift(pGrouple, iStartElt, iElts)
  1179. X    TPGrouple        pGrouple;
  1180. X    int            iStartElt, iElts;
  1181. X{
  1182. X    TVeosErr        iSuccess;
  1183. X    TPElt        pEltList;
  1184. X    int            iNewElts, iIndex;
  1185. X
  1186. X    
  1187. X    /** use stack vars for speed **/
  1188. X    
  1189. X    pEltList = pGrouple->pEltList;
  1190. X    iNewElts = pGrouple->iElts - iElts;
  1191. X    
  1192. X    
  1193. X    
  1194. X    iIndex = iStartElt;
  1195. X    while (iIndex < iNewElts) {
  1196. X    
  1197. X    pEltList[iIndex] = pEltList[iIndex + iElts];
  1198. X    
  1199. X    iIndex ++;
  1200. X    }
  1201. X    
  1202. X    iSuccess = Nancy_ResizeEltList(pGrouple, iNewElts);
  1203. X
  1204. X    return(iSuccess);
  1205. X
  1206. X    } /* Nancy_DownShift */
  1207. X/****************************************************************************************/
  1208. X
  1209. X
  1210. X/****************************************************************************************/
  1211. XTVeosErr Nancy_ElementToStreamAux(pElt, iLevel)
  1212. X    TPElt        pElt;
  1213. X    int            iLevel;
  1214. X{
  1215. X    TPElt        pEltList;
  1216. X    int            iElts, iEltIndex;
  1217. X    str63        sHostName;
  1218. X
  1219. X    if (pElt) {                /* sane? */
  1220. X
  1221. X    Nancy_StreamTabs(iLevel, GR_STREAM);
  1222. X
  1223. X    if (TESTFLAG(NANCY_EltMarkMask, pElt->iFlags))
  1224. X        fprintf(stderr, "> ");
  1225. X
  1226. X    PRINT_TIME(pElt->tLastMod, stderr);
  1227. X
  1228. X    
  1229. X    switch (pElt->iType) {
  1230. X        
  1231. X    case GR_vector:
  1232. X        fprintf(GR_STREAM, "#");
  1233. X        
  1234. X    case GR_grouple:
  1235. X        fprintf(GR_STREAM, "[\n");
  1236. X        
  1237. X        pEltList = pElt->u.pGr->pEltList;
  1238. X        iElts = pElt->u.pGr->iElts;
  1239. X        
  1240. X        for (iEltIndex = 0; iEltIndex < iElts; iEltIndex ++) {
  1241. X        
  1242. X        /** recurs */
  1243. X        Nancy_ElementToStreamAux(&pEltList[iEltIndex], iLevel + 1);
  1244. X        }
  1245. X        
  1246. X        Nancy_StreamTabs(iLevel, GR_STREAM);
  1247. X        fprintf(GR_STREAM, "]\n");
  1248. X        break;
  1249. X        
  1250. X    case GR_here:
  1251. X        fprintf(GR_STREAM, "^\n");
  1252. X        break;
  1253. X        
  1254. X    case GR_some:
  1255. X        fprintf(GR_STREAM, "*%d\n", pElt->u.iVal);
  1256. X        break;
  1257. X        
  1258. X    case GR_any:
  1259. X        fprintf(GR_STREAM, "**\n");
  1260. X        break;
  1261. X        
  1262. X    case GR_these:
  1263. X        fprintf(GR_STREAM, "@%d\n", pElt->u.iVal);
  1264. X        break;
  1265. X        
  1266. X    case GR_theseall:
  1267. X        fprintf(GR_STREAM, "@@\n");
  1268. X        break;
  1269. X        
  1270. X    case GR_float:
  1271. X        fprintf(GR_STREAM, "%.2f\n", pElt->u.fVal);
  1272. X        break;
  1273. X        
  1274. X    case GR_int:
  1275. X        fprintf(GR_STREAM, "%d\n", pElt->u.iVal);
  1276. X        break;
  1277. X        
  1278. X    case GR_string:
  1279. X        fprintf(GR_STREAM, "\"%s\"\n", pElt->u.pS);
  1280. X        break;
  1281. X        
  1282. X    case GR_prim:
  1283. X        fprintf(GR_STREAM, "'prim' %s\n", pElt->u.pS);
  1284. X        break;
  1285. X        
  1286. X    case GR_unspecified:
  1287. X        fprintf(GR_STREAM, "()\n");
  1288. X        break;
  1289. X        
  1290. X    default:
  1291. X        break;
  1292. X        
  1293. X        } /* switch */
  1294. X    }
  1295. X
  1296. X    return(VEOS_SUCCESS);
  1297. X
  1298. X    } /* Nancy_ElementToStreamAux */
  1299. X/****************************************************************************************/
  1300. X
  1301. X
  1302. X
  1303. X/****************************************************************************************/
  1304. XTVeosErr Nancy_TypeToString(iType, sName)
  1305. X    int        iType;
  1306. X    char    *sName;
  1307. X{
  1308. X    if (sName) {
  1309. X
  1310. X    switch (iType) {
  1311. X        
  1312. X    case GR_grouple:
  1313. X        strcpy(sName, "grouple");
  1314. X        break;
  1315. X    case GR_vector:
  1316. X        strcpy(sName, "vector");
  1317. X        break;
  1318. X    case GR_float:
  1319. X        strcpy(sName, "float");
  1320. X        break;
  1321. X    case GR_int:
  1322. X        strcpy(sName, "int");
  1323. X        break;
  1324. X    case GR_string:
  1325. X        strcpy(sName, "string");
  1326. X        break;
  1327. X    case GR_prim:
  1328. X        strcpy(sName, "prim");
  1329. X        break;
  1330. X    case GR_unspecified:
  1331. X        strcpy(sName, "unspecified");
  1332. X        break;
  1333. X    case GR_these:
  1334. X        strcpy(sName, "these");
  1335. X        break;
  1336. X    case GR_theseall:
  1337. X        strcpy(sName, "theseall");
  1338. X        break;
  1339. X    case GR_some:
  1340. X        strcpy(sName, "some");
  1341. X        break;
  1342. X    case GR_any:
  1343. X        strcpy(sName, "any");
  1344. X        break;
  1345. X    case GR_here:
  1346. X        strcpy(sName, "here");
  1347. X        break;
  1348. X    case GR_mark:
  1349. X        strcpy(sName, "mark");
  1350. X        break;
  1351. X    case GR_touch:
  1352. X        strcpy(sName, "touch");
  1353. X        break;
  1354. X    default:
  1355. X        break;
  1356. X        
  1357. X        } /* switch */
  1358. X    }
  1359. X
  1360. X    return(VEOS_SUCCESS);
  1361. X    
  1362. X    } /* Nancy_TypeToString */
  1363. X/****************************************************************************************/
  1364. X
  1365. X
  1366. X
  1367. X/****************************************************************************************/
  1368. XTVeosErr Nancy_StreamTabs(iTabs, pStream)
  1369. X    int        iTabs;
  1370. X    FILE    *pStream;
  1371. X{
  1372. X    while (iTabs-- > 0)
  1373. X    fprintf(pStream, "    ");
  1374. X
  1375. X    return(VEOS_SUCCESS);
  1376. X
  1377. X    } /* Nancy_StreamTabs */
  1378. X/****************************************************************************************/
  1379. X
  1380. X
  1381. X
  1382. X
  1383. X/****************************************************************************************/
  1384. XTVeosErr Nancy_SetupFastMem()
  1385. X{
  1386. X    TVeosErr        iSuccess;
  1387. X    int            i;
  1388. X
  1389. X    iSuccess = VEOS_SUCCESS;
  1390. X
  1391. X    TYPE_SIZES[GR_grouple] = TYPE_SIZES[GR_vector] = sizeof(TGrouple);
  1392. X
  1393. X    TYPE_SIZES[GR_prim] = TYPE_SIZES[GR_string] = 0;
  1394. X
  1395. X    TYPE_SIZES[GR_float] = 0;
  1396. X    TYPE_SIZES[GR_int] = 0;
  1397. X    TYPE_SIZES[GR_these] = 0;
  1398. X    TYPE_SIZES[GR_theseall] = 0; 
  1399. X    TYPE_SIZES[GR_some] = 0;
  1400. X    TYPE_SIZES[GR_any] = 0;
  1401. X    TYPE_SIZES[GR_here] = 0;
  1402. X
  1403. X
  1404. X    /* the elt list for the empty grouple is nil */
  1405. X    ALLOC_ELTS[0] = 0;
  1406. X
  1407. X    /* optimize for pair-type grouples coming from lisp */
  1408. X    ALLOC_ELTS[1] = 2;
  1409. X    ALLOC_ELTS[2] = 2;
  1410. X
  1411. X    for (i = 3; i < NANCY_AllocHashMax; i++)
  1412. X    ALLOC_ELTS[i] = ELTS_TO_ALLOCATE(i);
  1413. X
  1414. X    return(iSuccess);
  1415. X
  1416. X    } /* Nancy_SetupFastMem */
  1417. X/****************************************************************************************/
  1418. X
  1419. X
  1420. X                 
  1421. X
  1422. X
  1423. END_OF_FILE
  1424. if test 31245 -ne `wc -c <'kernel_private/src/nancy/nancy_fundamental.c'`; then
  1425.     echo shar: \"'kernel_private/src/nancy/nancy_fundamental.c'\" unpacked with wrong size!
  1426. fi
  1427. # end of 'kernel_private/src/nancy/nancy_fundamental.c'
  1428. fi
  1429. if test -f 'src/xlisp/xcore/doc/internals.doc' -a "${1}" != "-c" ; then 
  1430.   echo shar: Will not clobber existing file \"'src/xlisp/xcore/doc/internals.doc'\"
  1431. else
  1432. echo shar: Extracting \"'src/xlisp/xcore/doc/internals.doc'\" \(39828 characters\)
  1433. sed "s/^X//" >'src/xlisp/xcore/doc/internals.doc' <<'END_OF_FILE'
  1434. XBUGGO:  Add a generic class to sample diagram.
  1435. X
  1436. X------stuff to merge in to next release-----
  1437. XDate: Fri, 16 Nov 90 15:23:47 -0500
  1438. XFrom: "Ken Whedbee" <kcw@beach.cis.ufl.edu>
  1439. XTo: jsp@milton.u.washington.edu
  1440. XSubject: xlisp internals
  1441. X
  1442. X
  1443. XJeff -
  1444. X
  1445. XGreat job on the xlisp internals doc.  Xlisp has been needing this for
  1446. Xa long time ...
  1447. X
  1448. XSome extras that might be nice to have in your internals doc
  1449. Xare:
  1450. X
  1451. X1.  Give sort of a high level description of whats in each
  1452. X    xl*.c file.  Some distributions of the source have
  1453. X    this at the top of the file .. some dont.
  1454. X
  1455. X2.  How about outlining the basic flow of control in xlisp ?
  1456. X
  1457. X3.  For people adding funtions, to pick up a copy of
  1458. X    Steele's Common Lisp the Language
  1459. X
  1460. X
  1461. X>From stuff i ve read it sounds like David Betze is not going
  1462. Xto do any more work on xlisp.  He's been working on xscheme
  1463. Xlately, and considers it a better language (where common
  1464. Xlisp is the extended union of all the dialects of lisp, scheme
  1465. Xis the intersection of all the dialects :)  )
  1466. X
  1467. XIf new versions of xlisp are to become available, people
  1468. Xhacking on it will be the ones turning them out.  What would
  1469. Xyou think of getting people from comp.lang.lisp.x to
  1470. Xagree on a new version ?  To my version of xlisp i ve added
  1471. Xsomething like 80 new functions .. but i ve been pretty
  1472. Xmuch sitting on it and not releasing it.
  1473. X
  1474. X-------------------------------------------
  1475. XFrom: toma@tekgvs.LABS.TEK.COM (Tom Almy)
  1476. XNewsgroups: comp.lang.lisp.x
  1477. XSubject: Re: xlisp 2.1/winterp internals (26K long)
  1478. XDate: 16 Nov 90 21:13:29 GMT
  1479. XReply-To: toma@tekgvs.LABS.TEK.COM (Tom Almy)
  1480. XDistribution: comp
  1481. XOrganization: Tektronix, Inc., Beaverton,  OR.
  1482. X
  1483. X>I've just finished reading the xlisp 2.1 source code for the first
  1484. X>time.  The tutorial and reference material included with the winterp
  1485. X>distribution are well done, but I would have liked an overview of the
  1486. X>interpreter internals.  Here's a first cut at such a document.
  1487. X>Comments welcome...
  1488. X
  1489. XI have spend many hours going over the listings, fixing bugs, and making
  1490. Xextensions. I wish I had this when I started. But I do have a few comments.
  1491. X
  1492. X
  1493. X>xlenv and xlfenf are conceptually a single environment, although they
  1494. X>are implemented separately. [...]
  1495. X
  1496. X>The xlfenv environment is maintained strictly parallel to xlenv, but
  1497. X>is used to find function values instead of variable values.  The
  1498. X>separation may be partly for lookup speed and partly for historical
  1499. X>reasons.
  1500. X
  1501. XThey have to be maintained separately because let lexically binds values and
  1502. Xflet, labels, and macrolet lexically bind only functions. 
  1503. XFor instance consider:
  1504. X(defun x () x)
  1505. X(setq x 10)
  1506. X(let ((x 3)) (print x) (print (x)))
  1507. X
  1508. Xwill print 3 and 10.
  1509. X
  1510. Xwhile
  1511. X
  1512. X(flet ((x () (+ 1 x))) (print x) (print (x)))
  1513. X
  1514. Xwill print 10 and 11.
  1515. X
  1516. Xand 
  1517. X
  1518. X(let ((x 3)) (flet ((x () (+ 1 x))) (print x) (print (x))))
  1519. X
  1520. Xwill print 3 and 4.
  1521. X
  1522. XYou couldn't do this with a combined binding list.
  1523. X
  1524. X
  1525. X>The xldenv environment tracks the old values of global variables which
  1526. X>we have changed but intend to restore later to their original values,
  1527. X>particularly when we bind and unbind s_evalhook and s_applyhook
  1528. X>(*EVALHOOK* and *APPLYHOOK*).  (This is mostly to support the debug
  1529. X>facilities.)  It is a simple list of sym-val pairs,
  1530. X>treated as a stack.
  1531. X
  1532. Xxldenv tracks the dynamic binding (as opposed to lexical binding). A "flaw"
  1533. Xin xlisp is that there is no mechanism for declaring special variables
  1534. X(which would be always dynamically bound). You can dynamically bind
  1535. Xvariables with PROGV. If my memory serves, only PROGV, EVALHOOK and 
  1536. X(as I implemented it) APPLYHOOK dynamically bind variables.  For instance,
  1537. Xconsider the following variation of the LET example above:
  1538. X
  1539. X(defun x () x)
  1540. X(setq x 10)
  1541. X(progv '(x) '(3) (print x) (print (x)))
  1542. X
  1543. Xwill print 3 and 3. (When execution falls out of progv, the global x is
  1544. Xrebound to 10).
  1545. X
  1546. X
  1547. XThis is the best way to override global variable settings in an application,
  1548. Xsince the variables will be restored automatically on termination.
  1549. X
  1550. X
  1551. X>Obviously, several of the above types won't fit in a fixed-size
  1552. X>two-slot node.  The escape is to have them malloc() some memory
  1553. X>and have one of the slots point to it -- VECTOR is the archetype.  For
  1554. X>example, see xldmem.c:newvector().  To some extent, this malloc()
  1555. X>hack simply exports the memory- fragmentation problem to the C
  1556. X>malloc()/free() routines.  However, it helps keep xlisp simple, and it
  1557. X>has the happy side-effect of unpinning the body of the vector, so that
  1558. X>vectors can easily be expanded and contracted.
  1559. X
  1560. XXSCHEME which relies more heavily on arrays, maintains a pool of storage
  1561. Xto allocate arrays and strings, for which it does garbage collection
  1562. Xand (I believe) compaction as well. At any rate, my modified xlisp can
  1563. Xoptionally use the xcheme approach which has decided advantages in
  1564. Xprograms that use many arrays and strings since the memory does not
  1565. Xget fragmented. Enough said.
  1566. X
  1567. X
  1568. X>Xlisp pre-allocates nodes for all ascii characters, and for small
  1569. X>integers.  These nodes are never garbage-collected.
  1570. X
  1571. XThis also speeds up READ, and vastly reduces the number of nodes since
  1572. Xall identical characters and small integers are unique. The range of
  1573. Xsmall integers treated in this way is compilation settable.
  1574. X
  1575. X
  1576. X>As a practical matter, allocating all nodes in a single array is not
  1577. X>very sensible.  Instead, nodes are allocated as needed, in segments of
  1578. X>one or two thousand nodes, and the segments linked by a pointer chain
  1579. X>rooted at xldmem.c:segs.
  1580. X
  1581. XThe size of the segment is settable using the ALLOC function.
  1582. X
  1583. X>You create a symbol in xlisp by using the
  1584. X>single-quote operator: "'name", or by calling "(gensym)", or
  1585. X>indirectly in various ways.
  1586. X
  1587. XI would say that 'name is an indirect way to create a symbol. The direct
  1588. Xways are using MAKE-SYMBOL (for uninterned symbols) or INTERN (for interned
  1589. Xsymbols), or as you mentioned GENSYM (also uninterned). You can make READ
  1590. Xcreate an uninterned symbol by preceeding it with #:, otherwise all symbols
  1591. Xread by READ are interned.
  1592. X
  1593. XIn addition, when you make a symbol that starts with the colon character,
  1594. Xthe symbol is given itself as the value, otherwise the new symbol has no
  1595. Xvalue.
  1596. X
  1597. X
  1598. X>OBJECT is the root of the class hierarchy: everything you can send a
  1599. X>message to is of type OBJECT.  (Vectors, chars, integers and so forth
  1600. X>stand outside the object hierarchy -- you can't send messages to them.
  1601. X>I'm not sure why Dave did it this way.)
  1602. X
  1603. XProbably because the object facility is an extension of lisp. You can
  1604. Xcreate classes of these things. There is also efficiency considerations.
  1605. XThe only object oriented programming language I know of where everything
  1606. Xis an object is Smalltalk, but if you look at the implementation, it does
  1607. Xcheat at the low level to speed things up.
  1608. X
  1609. X> :isnew -- Does nothing
  1610. X
  1611. XIt does return the object!
  1612. X
  1613. X
  1614. X>FSUBR: A special primitive fn coded in C, which (like IF) wants its
  1615. X>arguments unevaluated.  
  1616. X
  1617. XThese are the "special forms"
  1618. X
  1619. X>We scan the MESSAGES list in the CLASS object of the recipient,
  1620. X>looking for a (message-symbol method) pair that matches our message
  1621. X>symbol.  If necessary, we scan the MESSAGES lists of the recipients
  1622. X>superclasses too.  (xlobj.c:sendmsg().)  Once we find it, we basically
  1623. X>do a normal function evaluation. (xlobjl.c:evmethod().)  Two oddities:
  1624. X>We need to replace the message-symbol by the recipient on the argument
  1625. X>stack to make things look normal, and we need to push an 'object'
  1626. X>stack entry on the xlenv environment so we remember which class is
  1627. X>handling the message.
  1628. X
  1629. X
  1630. XThe first "oddity" has an important side effect, when :answer was
  1631. Xused to build the method closure, an additional argument, "self", was
  1632. Xadded so that the method could access itself with the symbol self.
  1633. XThis argument stack fix supplies the needed argument. 
  1634. X
  1635. XThe reason for the second "oddity" is that the method's class is
  1636. Xneeded for SEND-SUPER. When one uses SEND-SUPER, the message lookup
  1637. Xbegins in the superclass of the method rather than the class of the
  1638. Xobject (as with SEND).
  1639. X
  1640. X>    xlstkcheck(3);    /* Make sure following xlsave */
  1641. X>                      /* calls won't overrun stack. */
  1642. X>    xlsave(list_ptr); /* Use xlsave1() if you don't */
  1643. X>    xlsave(float_ptr);/* do an xlstkcheck().        */
  1644. X>    xlsave(int_ptr);
  1645. X
  1646. Xxlsave also set the variable to nil. If you don't need to do that you
  1647. Xcan use xlprot instead of xlsave, or xlprot1 instead of xlsave1
  1648. X
  1649. X>xlapply, xlevform and sendmsg will issue an error if they encounter a
  1650. X>s_macro CLOSURE.  This is presumably because all macros are expanded
  1651. X>by xleval.c:xlclose when it builds a closure.
  1652. X
  1653. XYou are not allowed to use APPLY or FUNCALL with macros in Common
  1654. XLisp. There is no way provided to declare macro methods, nor do they
  1655. Xmake much sense (at least in my mind).
  1656. X
  1657. X>Neither xlapply nor sendmsg will handle FSUBRs.  This is presumably
  1658. X>a minor bug, left due to the difficulty of keeping arguments
  1659. X>unevaluated to that point. ?
  1660. X
  1661. XYou are not allowed to use APPLY or FUNCALL with special forms. There is
  1662. Xno way to declare methods using SUBRs or FSUBRs (the existing SUBR
  1663. Xmethods are initialized at load time).
  1664. X
  1665. XCorrected reply:
  1666. XCommon Lisp does not allow APPLYing a macro or special form (FSUBR).
  1667. XThis is based on the evaluation model.
  1668. XSince SEND is a subr, all of its arguments are already evaluated so it
  1669. Xis already too late to have macro or fsubr methods.
  1670. X
  1671. X>
  1672. X> Minor Mysteries:
  1673. X> ----------------
  1674. X
  1675. X>Why doesn't xlevform trace FSUBRs?  Is this a speed hack?
  1676. XGood question. Probably not a speed hack. You can't trace macros either.
  1677. X
  1678. X>Why do both xlobj.c:xloinit() and xlobj.c:obsymvols() initialize the
  1679. X>"object" and "class" variables?
  1680. X
  1681. Xxloinit creates the classes class and object, as well as the symbols, but
  1682. Xsets the C variables class and object to point to the class and object.
  1683. X
  1684. Xobsymbols just set the C variables by looking up the symbols. It is needed
  1685. Xbecause when you restore a workspace you don't create new objects but still
  1686. Xneed to know where the existing objects are (they might be in a different
  1687. Xlocation in the saved workspace). Notice that obsymbols is called by xlsymbols
  1688. Xwhich is called both when initializing a new workspace or restoring an old
  1689. Xworkspace.
  1690. X
  1691. X
  1692. XTom Almy
  1693. Xtoma@tekgvs.labs.tek.com
  1694. XStandard Disclaimers Apply
  1695. X
  1696. X-------------------------------------------
  1697. X
  1698. X
  1699. X
  1700. X----------------------------cut here---------------------------
  1701. X90Nov16 jsp@milton.u.washington.edu (Jeff Prothero).  Public Domain.
  1702. X
  1703. X                   +---------------------+
  1704. X                   | xlisp 2.1 internals |
  1705. X                   +---------------------+
  1706. X
  1707. X            "Trust the Source, Luke, trust the Source!"
  1708. X
  1709. X
  1710. X Who should read this?
  1711. X ---------------------
  1712. X
  1713. XAnyone poking through the C implementation of xlisp for the first
  1714. Xtime.  This is intended to provide a rough roadmap of the global xlisp
  1715. Xstructures and algorithms.  If you just want to write lisp code in
  1716. Xxlisp, you don't need to read this file -- go read xlisp.doc,
  1717. XXlispOOP.doc, and XlispRef.doc, in about that order.  If you want to
  1718. Xtinker with the xlisp implementation code, you should *still* read
  1719. Xthose three before reading this.  The following isn't intended to be
  1720. Xexhaustively precise -- that's what the source code is for!  It is
  1721. Xintended only to allow you a fighting change of understanding the code
  1722. Xthe first time through (instead of the third time).
  1723. X
  1724. XAt the bottom of the file you'll find an example of how to add new
  1725. Xprimitive functions to xlisp.
  1726. X
  1727. X
  1728. X
  1729. X What is an LVAL?
  1730. X ----------------
  1731. X
  1732. XAn "LVAL" is the C type for a generic pointer to an xlisp
  1733. Xgarbage-collectable something.  (Cons cell, object, string, closure,
  1734. Xsymbol, vector, whatever.)  Virtually every variable in the
  1735. Xinterpreter is an LVAL.  Cons cells contain two LVAL slots,
  1736. Xsymbols contains four LVAL slots, etc.
  1737. X
  1738. X
  1739. X
  1740. X What is the obarray?
  1741. X -------------------
  1742. X
  1743. XThe obarray is the xlisp symbol table.  More precisely, it is a
  1744. Xhashtable mapping ascii strings (SYMBOL names) to SYMBOLs.  (The name
  1745. X"obarray" is traditional but a bit of a misnomer, since it contains
  1746. Xonly xlisp SYMBOLs, and in particular contains no xlisp OBJECTs.)  It
  1747. Xis used when converting lisp expressions from text to internal form.
  1748. XSince it is a root for the garbage collector, it also serves to
  1749. Xdistinguish permanent global-variable SYMBOLs from other SYMBOLs --
  1750. Xyou can permanently protect a SYMBOL from the garbage collector by
  1751. Xentering it into the obarray.  This is called "interning" the SYMBOL.
  1752. XThe obarray is called "obarray" in C and "*OBARRAY*" in xlisp. It is
  1753. Xphysically implemented as a VECTOR-valued SYMBOL.
  1754. X
  1755. X
  1756. X
  1757. X The Interpreter Stacks
  1758. X ----------------------
  1759. X
  1760. Xxlisp uses two stacks, an "evaluation stack" and an "argument stack".
  1761. XBoth are roots for the garbage collector.  The evaluation stack is
  1762. Xlargely private to the interpreter and protects internal values from
  1763. Xgarbage collection, while the argument stack holds the conventional
  1764. Xuser-visible stackframes.
  1765. X
  1766. X
  1767. XThe evaluation stack is an EDEPTH-long array of "LVAL" allocated by
  1768. Xxldmem.c:xlminit().  It grows zeroward.
  1769. X
  1770. Xxlstkbase points to the zero-near end of the evaluation stack.
  1771. X
  1772. Xxlstktop points to the zero-far end of the evaluation stack; the
  1773. Xoccupied part of the stack lies between xlstack and xlstktop.  NOTE
  1774. Xthat xlstktop is *NOT* the top of the stack in the conventional sense
  1775. Xof indicating the most recent entry on the stack: xlstktop is a static
  1776. Xbounds pointer which never changes once the stack is allocated.
  1777. X
  1778. Xxlstack starts at the zero-far end of the evaluation stack.  *xlstack
  1779. Xis the most recent LVAL on the stack.  The garbage collector MARKs
  1780. Xeverything reachable from the evaluation stack (among other things),
  1781. Xso we frequently push things on this stack while C code is
  1782. Xmanipulating them. (Via xlsave(), xlprotect(), xlsave1(), xlprot1().)
  1783. X
  1784. X
  1785. XThe argument stack is an ADEPTH-long array of "LVAL".  It also grows
  1786. Xzeroward.  The evaluator pushes arguments on the argument stack at the
  1787. Xstart of a function call (form evaluation).  Built-in functions
  1788. Xusually eat them directly off the stack.  For user-lisp functions
  1789. Xxleval.c:evfun() pops them off the stack and binds them to the
  1790. Xappropriate symbols before beginning execution of the function body
  1791. Xproper.
  1792. X
  1793. Xxlargstkbase is the zero-near end of argument stack.
  1794. X
  1795. Xxlargstktop is the zero-far end of argument stack.  Like xlstktop,
  1796. Xxlargstktop is a static bounds pointer which never changes after
  1797. Xthe stack is allocated.
  1798. X
  1799. X*xlsp ("sp"=="stack pointer") is the most recent item on the argument stack.
  1800. X
  1801. Xxlfp ("fp"=="frame pointer") is the base of the current stackframe.
  1802. X
  1803. X
  1804. X
  1805. X  What is a context?
  1806. X  ------------------
  1807. X
  1808. XAn xlisp "context" is something like a checkpoint, recording a
  1809. Xparticular point buried in the execution history so that we can
  1810. Xabort/return back to it.  Contexts are used to implement call/return,
  1811. Xcatch/throw, signals, gotos, and breaks.  xlcontext points to the
  1812. Xchain of active contexts, the top one being the second-newest active
  1813. Xcontext.  (The newest -- that is, current -- active context is
  1814. Ximplemented by the variables xlstack xlenv xlfenv xldenv xlcontext
  1815. Xxlargv xlargc xlfp xlsp.)  Context records are written by
  1816. Xxljump.c:xlbegin() and read by xljump.c:xljump().  Context records are
  1817. XC structures on the C program stack; They are not in the dynamic
  1818. Xmemory pool or on the lisp execution or argument stacks.
  1819. X
  1820. X
  1821. X
  1822. X  What is an environment?
  1823. X  -----------------------
  1824. X
  1825. XAn environment is basically a store of symbol-value pairs, used to
  1826. Xresolve variable references by the lisp program.  xlisp maintains
  1827. Xthree environments, in the global variables xlenv, xlfenv and xldenv.
  1828. X
  1829. Xxlenv and xlfenf are conceptually a single environment, although they
  1830. Xare implemented separately.  They are linked-list stacks which are
  1831. Xpushed when we enter a function and popped when we exit it.  We also
  1832. Xswitch xlenv+xlfenf environments entirely when we begin executing a
  1833. Xnew closure (user-fn written in lisp).
  1834. X
  1835. XThe xlenv environment is the most heavily used environment.  It is
  1836. Xused to resolve everyday data references to local variables.  It
  1837. Xconsists of a list of frames (and objects).  Each frame is a list of
  1838. Xsym-val pairs.  In the case of an object, we check all the instance
  1839. Xand class variables of the object, then do the same for its
  1840. Xsuperclass, until we run out of superclasses.
  1841. X
  1842. XThe xlfenv environment is maintained strictly parallel to xlenv, but
  1843. Xis used to find function values instead of variable values.  The
  1844. Xseparation may be partly for lookup speed and partly for historical
  1845. Xreasons.
  1846. X
  1847. XWhen we send a message, we set xlenv to the value it had when the
  1848. Xmessage CLOSURE was built, then push on (obj msg-class), where
  1849. Xmsg-class is the [super]class defining the method.  (We also set
  1850. Xxlfenv to the value xlfenv had when the method was built.)  This makes
  1851. Xthe object instance variables part of the environment, and saves the
  1852. Xinformation needed to correctly resolve references to class variables,
  1853. Xand to implement SEND-SUPER.
  1854. X
  1855. XThe xldenv environment tracks the old values of global variables which
  1856. Xwe have changed but intend to restore later to their original values,
  1857. Xparticularly when we bind and unbind s_evalhook and s_applyhook
  1858. X(*EVALHOOK* and *APPLYHOOK*).  (This is mostly to support the debug
  1859. Xfacilities.)  It is a simple list of sym-val pairs,
  1860. Xtreated as a stack.
  1861. X
  1862. XThese environments are manipulated in C via the xlisp.h macros
  1863. Xxlframe(e), xlbind(s,v), xlfbind(s,v), xlpbind(s,v,e), xldbind(s,v),
  1864. Xxlunbind(e).
  1865. X
  1866. X
  1867. X
  1868. X  How are xlisp entities stored and identified?
  1869. X  ---------------------------------------------
  1870. X
  1871. XConceptually, xlisp manages memory as a single array of fixed-size
  1872. Xobjects.  Keeping all objects the same size simplifies memory
  1873. Xmanagement enormously, since any object can be allocated anywhere, and
  1874. Xcomplex compacting schemes aren't needed.  Every LVAL pointer points
  1875. Xsomewhere in this array.  Every xlisp object has the basic format
  1876. X(xldmem.h:typdef struct node)
  1877. X
  1878. X struct node {
  1879. X     char n_type;
  1880. X     char n_flags;
  1881. X     LVAL car;
  1882. X     LVAL cdr;
  1883. X }
  1884. X
  1885. Xwhere n_type is one of:
  1886. X
  1887. X FREE     A node on the freelist.
  1888. X SUBR     A function implemented in C. (Needs evaluated arguments.)
  1889. X FSUBR    A special function implemented in C. (Needs unevaluated arguments).
  1890. X CONS     A regular lisp cons cell.
  1891. X SYMBOL   A symbol.
  1892. X FIXNUM   An integer.
  1893. X FLONUM   A floating-point number.
  1894. X STRING   A string.
  1895. X OBJECT   Any object, including class objects.
  1896. X STREAM   An input or output file.
  1897. X VECTOR      A variable-size array of LVALs.
  1898. X CLOSURE  Result of DEFUN or LAMBDA -- a function written in lisp.
  1899. X CHAR      An ascii character.
  1900. X USTREAM  An internal stream.
  1901. X STRUCT      A structure.
  1902. X
  1903. XMessages may be sent only to nodes with n_type == OBJECT.
  1904. X
  1905. XObviously, several of the above types won't fit in a fixed-size
  1906. Xtwo-slot node.  The escape is to have them malloc() some memory
  1907. Xand have one of the slots point to it -- VECTOR is the archetype.  For
  1908. Xexample, see xldmem.c:newvector().  To some extent, this malloc()
  1909. Xhack simply exports the memory- fragmentation problem to the C
  1910. Xmalloc()/free() routines.  However, it helps keep xlisp simple, and it
  1911. Xhas the happy side-effect of unpinning the body of the vector, so that
  1912. Xvectors can easily be expanded and contracted.
  1913. X
  1914. XThe garbage collector has special-case code for each of the above node
  1915. Xtypes, so it can find all LVAL slots and recycle any malloc()ed ram
  1916. Xwhen a node is garbage-collected.
  1917. X
  1918. XXlisp pre-allocates nodes for all ascii characters, and for small
  1919. Xintegers.  These nodes are never garbage-collected.
  1920. X
  1921. XAs a practical matter, allocating all nodes in a single array is not
  1922. Xvery sensible.  Instead, nodes are allocated as needed, in segments of
  1923. Xone or two thousand nodes, and the segments linked by a pointer chain
  1924. Xrooted at xldmem.c:segs.
  1925. X
  1926. X
  1927. X
  1928. X  How are vectors implemented?
  1929. X  ----------------------------
  1930. X
  1931. XAn xlisp vector is a generic array of LVAL slots.  Vectors are also
  1932. Xthe canonical illustration of xlisp's escape mechanism for node types
  1933. Xwhich need more than two LVAL slots (the maximum possible in the
  1934. Xfixed-size nodes in the dynamic memory pool).  The node CAR/CDR slots
  1935. Xfor a vector hold a size field plus a pointer to a malloc()ed ram
  1936. Xchunk, which is automatically free()ed when the vector is
  1937. Xgarbage-collected.
  1938. X
  1939. Xxldmem.h defines macros for reading and writing vector fields and
  1940. Xslots: getsize(), getelement() and setelement().  It also defines
  1941. Xmacros for accessing each of the other types of xlisp nodes.
  1942. X
  1943. X
  1944. X
  1945. X  How are strings implemented?
  1946. X  ---------------------------- 
  1947. X
  1948. XStrings work much like vectors: The node has a pointer to a malloc()ed
  1949. Xram chunk which is automatically free()ed when the string gets
  1950. Xgarbage-collected.
  1951. X
  1952. X
  1953. X
  1954. X How are symbols implemented?
  1955. X ----------------------------
  1956. X
  1957. XA symbol is a generic user-visible lisp variable, with separate slots
  1958. Xfor print name, value, function, and property list.  Any or all of
  1959. Xthese slots (including name) may be NIL.  You create a symbol in C by
  1960. Xcalling "xlmakesym(name)" or "xlenter(name)" (to make a symbol and
  1961. Xenter it in the obarray). You create a symbol in xlisp by using the
  1962. Xsingle-quote operator: "'name", or by calling "(gensym)", or
  1963. Xindirectly in various ways.  Most of the symbol-specific code in the
  1964. Xinterpreter is in xlsym.c.
  1965. X
  1966. XPhysically, a symbol is implemented like a four-slot vector.
  1967. X
  1968. XRandom musing: Abstractly, the LISP symbols plus cons cells (etc)
  1969. Xconstitute a single directed graph, and the symbols mark spots where
  1970. Xnormal recursive evaluation should stop.  Normal lisp programming
  1971. Xpractice is to have a symbol in every cycle in the graph, so that
  1972. Xrecursive traversal can be done without MARK bits.
  1973. X
  1974. X
  1975. X
  1976. X  How are closures implemented?
  1977. X  -----------------------------
  1978. X
  1979. XA closure, the return value from a lambda, is a regular coded-in-lisp
  1980. Xfn.  Physically, it is implemented like an eleven-slot vector, with the
  1981. Xnode n_type field hacked to contain CLOSURE instead of VECTOR. The
  1982. Xvector slots contain:
  1983. X
  1984. X name   symbol -- 1st arg of DEFUN.  NIL for LAMBDA closures.
  1985. X type   (s_lambda or s_macro). Must be s_lambda to be executable.
  1986. X args   List of "required" formal arguments (as symbols)
  1987. X oargs  List of "optional" args, each like: (name (default specified-p))
  1988. X rest   Name of "&rest" formal arg, else NIL.
  1989. X kargs  keyword args, each like: ((':foo 'bar default specified-p))
  1990. X aargs  &aux vars, each like: (('arg default))
  1991. X body   actual code (as lisp list) for fn.
  1992. X env    value of xlenv when the closure was built.  NIL for macros.
  1993. X fenv   value of xlfend when the closure was built. NIL for macros.
  1994. X lambda The original formal args list in the DEFUN or LAMBDA.
  1995. X
  1996. XThe lambda field is for printout purposes.  The remaining fields store
  1997. Xa predigested version of the formal args list.  This is a limited form
  1998. Xof compilation: by processing the args list at closure-creation time,
  1999. Xwe reduce the work needed during calls to the closure.
  2000. X
  2001. X
  2002. X
  2003. X  How are objects implemented?
  2004. X  ----------------------------
  2005. X
  2006. XAn object is implemented like a vector, with the size determined by
  2007. Xthe number of instance variables.  The first slot in the vector points
  2008. Xto the class of the object; the remaining slots hold the instance
  2009. Xvariables for the object.  An object needs enough slots to hold all
  2010. Xthe instance variables defined by its class, *plus* all the instance
  2011. Xvariables defined by all of its superclasses.
  2012. X
  2013. X
  2014. X
  2015. X  How are classes implemented?
  2016. X  ----------------------------
  2017. X
  2018. XA class is a specific kind of object, hence has a class pointer plus
  2019. Xinstance variables.  All classes have the following instance variables:
  2020. X
  2021. X MESSAGES   A list of (interned-symbol method-closure) pairs.
  2022. X IVARS        Instance variable names: A list of interned symbols.
  2023. X CVARS      Class variable names:    A list of interned symbols.
  2024. X CVALS      Class variable values:   A vector of values.
  2025. X SUPERCLASS A pointer to the superclass.
  2026. X IVARCNT    Number of class instance variables, as a fixnum.
  2027. X IVARTOTAL  Total number of instance variables, as a fixnum.
  2028. X
  2029. XIVARCNT is the count of the number of instance variables defined by
  2030. Xour class.  IVARTOTAL is the total number of instance variables in an
  2031. Xobject of this class -- IVARCNT for this class plus the IVARCNTs from
  2032. Xall of our superclasses.
  2033. X
  2034. X
  2035. X
  2036. X
  2037. X  How is the class hierarchy laid out?
  2038. X  ------------------------------------
  2039. X
  2040. XThe fundamental objects are the OBJECT and CLASS class objects.  (Both
  2041. Xare instances of class CLASS, and since CLASSes are a particular kind
  2042. Xof OBJECT, both are also objects, with n_type==OBJECT.  Bear with me!)
  2043. X
  2044. XOBJECT is the root of the class hierarchy: everything you can send a
  2045. Xmessage to has OBJECT as its class or super*class.  (Vectors, chars,
  2046. Xintegers and so forth stand outside the object hierarchy -- you can't
  2047. Xsend messages to them.  I'm not sure why Dave did it this way.) OBJECT
  2048. Xdefines the messages:
  2049. X
  2050. X :isnew -- Does nothing
  2051. X :class -- Returns contents of class-pointer slot.
  2052. X :show  -- Prints names of obj, obj->class and instance vars.
  2053. X
  2054. XSince a CLASS is a specialized type of OBJECT (with instance variables
  2055. Xlike MESSAGES which generic OBJECTs lack), class CLASS has class
  2056. XOBJECT as its superclass.  The CLASS object defines the messages:
  2057. X
  2058. X :new     -- Create new object with self.IVARTOTAL LVAR slots, plus
  2059. X            one for the class pointer. Point class slot to self.
  2060. X            Set new.n_type char to OBJECT.
  2061. X :isnew     -- Fill in IVARS, CVARS, CVALS, SUPERCLASS, IVARCNT and
  2062. X            IVARTOTAL, using parameters from :new call.  (The
  2063. X            :isnew msg inherits the :new msg parameters because
  2064. X            the  :isnew msg is generated automatically after
  2065. X            each :new   msg, courtesy of a special hack in
  2066. X            xlobj.c:sendmsg().)
  2067. X :answer -- Add a (msg closure) pair to self.MESSAGES.
  2068. X
  2069. X
  2070. X
  2071. XHere's a figure to summarize the above, with a generic object thrown
  2072. Xin for good measure.  Note that all instances of CLASS will have a
  2073. XSUPERCLASS pointer, but no normal object will.  Note also that the
  2074. Xmessages known to an object are those which can be reached by
  2075. Xfollowing exactly one Class Ptr and then zero or more Superclass Ptrs.
  2076. XFor example, the generic object can respond to :ISNEW, :CLASS and
  2077. X:SHOW, but not to :NEW or :ANSWER.  (The functions implementing the
  2078. Xgiven messages are shown in parentheses.)
  2079. X
  2080. X                    NIL
  2081. X                     ^
  2082. X                     |
  2083. X                     |Superclass Ptr
  2084. X                     |
  2085. X                Msg+--------+
  2086. X :isnew (xlobj.c:obisnew) <----|  class |Class Ptr
  2087. X :class (xlobj.c:obclass) <----| OBJECT |------------+
  2088. X :show    (xlobj.c:objshow) <----|        |            |
  2089. X                   +--------+            |
  2090. X       +---------+                ^  ^               |
  2091. X       | generic |Class Ptr       |  |               |
  2092. X       | object  |----------------+  |Superclass Ptr |
  2093. X       +---------+             |               |
  2094. X                Msg+--------+            |
  2095. X :isnew    (xlobj.c:clnew)      <----| class  |Class Ptr   |
  2096. X :new    (xlobj.c:clisnew) <----| CLASS  |--------+   |
  2097. X :answer(xlobj.c:clanswer)<----|        |        |   |
  2098. X                   +--------+        |   |
  2099. X                  ^  ^           |   |
  2100. X                  |  |           |   |
  2101. X                  |  +-----------+   |
  2102. X                  +------------------+
  2103. X
  2104. X
  2105. XThus, class CLASS inherits the :CLASS and :SHOW messages from class
  2106. XOBJECT, overrides the default :ISNEW message, and provides new
  2107. Xmessages :NEW and :ANSWER.
  2108. X
  2109. XNew classes are created by (send CLASS :NEW ...) messages.  Their
  2110. XClass Ptr will point to CLASS.  By default, they will have OBJECT as
  2111. Xtheir superclass, but this can be overridden by the second optional
  2112. Xargument to :NEW.
  2113. X
  2114. XThe above basic structure is set up by xlobj.c:xloinit().
  2115. X
  2116. X
  2117. X
  2118. X  How do we look up the value of a variable?
  2119. X  ------------------------------------------
  2120. X
  2121. XWhen we're cruising along evaluating an expression and encounter a
  2122. Xsymbol, the symbol might refer to a global variable, an instance
  2123. Xvariable, or a class variable in any of our superclasses.  Figuring
  2124. Xout which means digging through the environment.  The canonical place
  2125. Xthis happens is in xleval.c:xleval(), which simply passes the buck to
  2126. Xxlsym.c:xlgetvalue(), which in turn passes the buck to
  2127. Xxlxsym.c:xlxgetvalue(), where the fun of scanning down xlenv begins.
  2128. XThe xlenv environment looks something like
  2129. X
  2130. X     Backbone    Environment frame contents
  2131. X     --------    --------------------------
  2132. Xxlenv --> frame      ((sym val) (sym val) (sym val) ... )
  2133. X      frame      ...
  2134. X      object     (obj msg-class)
  2135. X      frame      ...
  2136. X      object     ...
  2137. X      frame      ...
  2138. X      ...
  2139. X
  2140. XThe "frame" lines are due to everyday nested constructs like LET
  2141. Xexpressions, while the "object" lines represent an object environment
  2142. Xentered via a message send.  xlxgetvalue scans the enviroment left to
  2143. Xright, and then top to bottom.  It scans down the regular environment
  2144. Xframes itself, and calls xlobj.c:xlobjgetvalue() to search the object
  2145. Xenvironment frames.
  2146. X
  2147. Xxlobjgetvalue() first searches for the symbol in the msg-class, then
  2148. Xin all the successive superclasses of msg-class.  In each class, it
  2149. Xfirst checks the list of instance-variable names in the IVARS slot,
  2150. Xthen the list of class-variables name in the CVARS slot.
  2151. X
  2152. X  
  2153. X
  2154. X  How are function calls implemented?
  2155. X  -----------------------------------
  2156. X
  2157. Xxleval.c contains the central expression-evaluation code.
  2158. Xxleval.c:xleval() is the standard top-level entrypoint.  The two
  2159. Xcentral functions are xleval.c:xlevform() and xleval.c:evfun().
  2160. Xxlevform() can evaluate four kinds of expression nodes:
  2161. X
  2162. XSUBR: A normal primitive fn coded in C.  We call evpushargs() to
  2163. Xevaluate and push the arguments, then call the primitive.
  2164. X
  2165. XFSUBR: A special primitive fn coded in C, which (like IF) wants its
  2166. Xarguments unevaluated.  We call pushargs() (instead of evpushargs())
  2167. Xand then the C fn.
  2168. X
  2169. XCLOSURE: A preprocessed written-in-lisp fn from a DEFUN or LAMBDA.  We
  2170. Xcall evpushargs() and then evfun().
  2171. X
  2172. XCONS: We issue an error if CONS.car isn't a LAMBDA, otherwise we call
  2173. Xxleval.c:xlclose() to build a CLOSURE from the LAMBDA, and fall into
  2174. Xthe CLOSURE code.
  2175. X
  2176. XThe common thread in all the above cases is that we call evpushargs()
  2177. Xor pushargs() to push all the arguments on the evaluation stack,
  2178. Xleaving the number and location of the arguments in the global
  2179. Xvariables xlargc and xlargv.  The primitive C functions consume
  2180. Xtheir arguments directly from the argument stack.
  2181. X
  2182. Xxleval.c:evfun() evaluates a CLOSURE by:
  2183. X
  2184. X(1) Switching xlenv and xlfenv to the values they had when
  2185. Xthe CLOSURE was built. (These values are recorded in the CLOSURE.)
  2186. X
  2187. X(2) Binding the arguments to the environment.  This involves scanning
  2188. Xthrough the section of the argument stack indicated by xlargc/xlargv,
  2189. Xusing information from the CLOSURE to resolve keyword arguments
  2190. Xcorrectly and assign appropriate default values to optional arguments,
  2191. Xamong other things.
  2192. X
  2193. X(3) Evaluating the body of the function via xleval.c:xleval().
  2194. X
  2195. X(4) Cleaning up and restoring the original environment.
  2196. X
  2197. X
  2198. X
  2199. X  How are message-sends implemented?
  2200. X  ----------------------------------
  2201. X
  2202. XWe scan the MESSAGES list in the CLASS object of the recipient,
  2203. Xlooking for a (message-symbol method) pair that matches our message
  2204. Xsymbol.  If necessary, we scan the MESSAGES lists of the recipient's
  2205. Xsuperclasses too.  (xlobj.c:sendmsg().)  Once we find it, we basically
  2206. Xdo a normal function evaluation. (xlobjl.c:evmethod().)  Two oddities:
  2207. XWe need to replace the message-symbol by the recipient on the argument
  2208. Xstack to make things look normal, and we need to push an 'object'
  2209. Xstack entry on the xlenv environment so we remember which class is
  2210. Xhandling the message.
  2211. X
  2212. X
  2213. X
  2214. X  How is garbage collection implemented?
  2215. X  --------------------------------------
  2216. X
  2217. XThe dynamic memory pool managed by xlisp consists of a chain of memory
  2218. Xsegments (xldmem.h:struct segment) rooted at global C variable "segs".
  2219. XEach segment contains an array of "struct node"s plus a pointer to the
  2220. Xnext segment.  Each node contains a n_type field and a MARK bit, which
  2221. Xis zero except during garbage collection.
  2222. X
  2223. XXlisp uses a simple, classical mark-and-sweep garbage collector.  When
  2224. Xit runs out of memory (fnodes==NIL), it does a recursive traversal
  2225. Xsetting the MARK flag on all nodes reachable from the obarray, the
  2226. Xthree environments xlenv/xlfenv/xldenv, and the evaluation and
  2227. Xargument stacks.  (A "switch" on the n_type field tells us how to find
  2228. Xall the LVAL slots in the node (plus associated storage), and a
  2229. Xpointer-reversal trick lets us avoid using too much stack space during
  2230. Xthe traversal.)  sweep() then adds all un-MARKed LVALs to fnodes, and
  2231. Xclears the MARK bit on the remaining nodes.  If this fails to produce
  2232. Xenough free nodes, a new segment is malloc()ed.
  2233. X
  2234. XThe code to do this stuff is mostly in xldmem.c.
  2235. X
  2236. X
  2237. X
  2238. X How do I add a new primitive fn to xlisp?
  2239. X -----------------------------------------
  2240. X
  2241. XAdd a line to the end of xlftab.c:funtab[].  This table contains a
  2242. Xlist of triples:
  2243. X
  2244. XThe first element of each triple is the function name as it will
  2245. Xappear to the programmer. Make it all upper case.
  2246. X
  2247. XThe second element is S (for SUBR) if (like most fns) your function
  2248. Xwants its arguments pre-evaluated, else F (for FSUBR).
  2249. X
  2250. XThe third element is the name of the C function to call.
  2251. X
  2252. XRemember that your arguments arrive on the xlisp argument stack rather
  2253. Xthan via the usual C parameter mechanism.
  2254. X
  2255. XCAUTION: Try to keep your files separate from generic xlisp files, and
  2256. Xto minimize the number of changes you make in the generic xlisp files.
  2257. XThis way, you'll have an easier time re-installing your changes when
  2258. Xnew versions of xlisp come out.  For example, if you are going to add
  2259. Xmany primitive functions to your xlisp, use an #include file rather
  2260. Xthan putting them all in xlftab.c.  It's a good idea to put a marker
  2261. X(like a comment with your initials) on each line you change or insert
  2262. Xin the generic xlisp fileset.
  2263. X
  2264. XCAUTION: Remember that you usually need to protect the LVAL variables
  2265. Xin your function from the garbage-collector.  It never hurts to do
  2266. Xthis, and often produces obscure bugs if you do not.  You protect
  2267. Xuninitialized local variables with xlsave1() and initialized local
  2268. Xvariables with xlprot1().
  2269. X
  2270. XBE CAREFUL NOT TO PROTECT UNINITIALIZED LOCAL VARIABLES WITH XLPROT1()
  2271. XOR XLPROTECT()!  This will appear to work fine until garbage
  2272. Xcollection happens at an inconvenient moment, at which point the
  2273. Xgarbage collector will wind up following your uninitialized pointer
  2274. Xoff to never-never land.
  2275. X
  2276. XNote: If you have several pointers to protect, you can save a little
  2277. Xruntime and codespace by using
  2278. Xxlstkcheck(number-of-variables-to-protect) followed by xlsave()s and
  2279. Xxlprotect()s instead of the more expensive xlsave1()s and xlprot1()s.
  2280. X
  2281. XGeneric code for a new primitive fn:
  2282. X
  2283. X/* xlsamplefun - do useless stuff.        */
  2284. X/* Called like (samplefun '(a c b) 1 2.0) */
  2285. XLVAL xlsamplefun()
  2286. X{
  2287. X    /* Variables to hold the arguments: */
  2288. X    LVAL    list_arg, integer_arg, float_arg;
  2289. X
  2290. X    /* Get the arguments, with appropriate errors */
  2291. X    /* if any are of the wrong type.  Look in     */
  2292. X    /* xlisp.h for macros to read other types of  */
  2293. X    /* arguments.  Look in xlmath.c for examples  */
  2294. X    /* of functions which can handle an argument  */
  2295. X    /* which may be either int or float:          */
  2296. X    list_arg    = xlgalist()  ;  /* "XLisp Get A LIST"   */
  2297. X    integer_arg = xlgafixnum();  /* "XLisp Get A FIXNUM" */
  2298. X    float_arg   = xlgaflonum();  /* "XLisp Get A FLONUM" */
  2299. X
  2300. X    /* Issue an error message if there are any extra arguments: */
  2301. X    xllastarg();
  2302. X
  2303. X
  2304. X
  2305. X    /* Call a separate C function to do the actual  */
  2306. X    /* work.  This way, the main function can       */
  2307. X    /* be called from both xlisp code and C code.   */
  2308. X    /* By convention, the name of the xlisp wrapper */
  2309. X    /* starts with "xl", and the native C function  */
  2310. X    /* has the same name minus the "xl" prefix:     */
  2311. X    return samplefun( list_arg, integer_arg, float_arg );
  2312. X}
  2313. XLVAL samplefun( list_arg, integer_arg, float_arg )
  2314. XLVAL            list_arg, integer_arg, float_arg;
  2315. X{
  2316. X    FIXTYPE val_of_integer_arg;
  2317. X    FLOTYPE val_of_float_arg;
  2318. X
  2319. X    /* Variables which will point to LISP objects: */
  2320. X    LVAL result;
  2321. X    LVAL list_ptr;
  2322. X    LVAL float_ptr;
  2323. X    LVAL int_ptr;
  2324. X
  2325. X    /* Protect our internal pointers by */
  2326. X    /* pushing them on the evaluation   */
  2327. X    /* stack so the garbage collector   */
  2328. X    /* can't recycle them in the middle */
  2329. X    /* of the routine:                  */
  2330. X    xlstkcheck(4);    /* Make sure following xlsave */
  2331. X                      /* calls won't overrun stack. */
  2332. X    xlsave(list_ptr); /* Use xlsave1() if you don't */
  2333. X    xlsave(float_ptr);/* do an xlstkcheck().        */
  2334. X    xlsave(int_ptr);
  2335. X    xlsave(result);
  2336. X
  2337. X    /* Semantic check, illustrating use of xlfail(): */
  2338. X    if (list_ptr == NULL) {
  2339. X        xlfail("null list");
  2340. X        /* Won't return. */
  2341. X    }
  2342. X
  2343. X    /* Create an internal list structure, protected */
  2344. X    /* against garbage collection until we exit fn: */
  2345. X    list_ptr = cons(list_arg,list_arg);
  2346. X
  2347. X    /* Get the actual values of our fixnum and flonum: */
  2348. X    val_of_integer_arg = getfixnum( integer_arg );
  2349. X    val_of_float_arg   = getflonum( float_arg   );
  2350. X
  2351. X    /* Semantic check, illustrating use of xlerror(): */
  2352. X    if (val_of_integer_arg < -2) {
  2353. X        xlerror("bad integer",cvfixnum(val_of_integer_arg));
  2354. X        /* Won't return. */
  2355. X    }
  2356. X
  2357. X
  2358. X
  2359. X    /*******************************************/
  2360. X    /* You can have any amount of intermediate */
  2361. X    /* computations at this point in the fn... */
  2362. X    /*******************************************/
  2363. X
  2364. X
  2365. X    /* Make new numeric values to return: */
  2366. X    integer_ptr = cvfixnum( val_of_integer_arg * 3   );
  2367. X    float_ptr   = cvflonum( val_of_float_arg   * 3.0 );
  2368. X
  2369. X    /* Cons it all together to produce a return value: */
  2370. X    result = cons( float_ptr,   NIL    );
  2371. X    result = cons( integer_ptr, result );
  2372. X    result = cons( list_ptr,    result );
  2373. X
  2374. X    /* Restore the stack, canceling the xlsave()s: */
  2375. X    xlpopn(4); /* Use xlpop() for a single argument.*/
  2376. X
  2377. X    return result;
  2378. X}
  2379. X
  2380. X
  2381. X
  2382. X Example of what NOT to do:
  2383. X --------------------------
  2384. X
  2385. XHere's a function I wrote which does *NOT* correctly prevent the
  2386. Xgarbage collector from stealing its dynamically allocated cells:
  2387. X
  2388. XLVAL incorrect_Point_To_List( p )/*DON'T USE THIS CODE! */
  2389. Xgeo_point*              p;
  2390. X/*-
  2391. X    Convert point to (x y z) list.
  2392. X-*/
  2393. X{
  2394. X    LVAL result;
  2395. X    xlsave1(result);
  2396. X    result = cons(              /* THIS CODE IS BROKEN! */
  2397. X        cvflonum(     p->x), /* THIS CODE IS BROKEN! */
  2398. X        cons(            /* THIS CODE IS BROKEN! */
  2399. X            cvflonum(    p->y), /* THIS CODE IS BROKEN! */
  2400. X            cons(        /* THIS CODE IS BROKEN! */
  2401. X                cvflonum(p->z),    /* THIS CODE IS BROKEN! */
  2402. X                NIL        /* THIS CODE IS BROKEN! */
  2403. X            )            /* THIS CODE IS BROKEN! */
  2404. X        )            /* THIS CODE IS BROKEN! */
  2405. X    );                /* THIS CODE IS BROKEN! */
  2406. X    xlpop();
  2407. X    return result;
  2408. X}
  2409. X
  2410. XThe problem with the above function is that the "z" cell will be
  2411. Xallocated first, and is not protected during the allocation of the "y"
  2412. Xflonum (or vice versa, depending on the order the compiler chooses to
  2413. Xevaluate these arguments). Similarly, the "y" cell is not protected
  2414. Xduring allocation of the "x" flonum. Here is a correct version, in
  2415. Xwhich "result" always protects the list-to-date:
  2416. X
  2417. XLVAL correct_Point_To_List( p )
  2418. Xgeo_point*            p;
  2419. X/*-
  2420. X    Convert point to (x y z) list.
  2421. X-*/
  2422. X{
  2423. X    LVAL result;
  2424. X    xlsave1(result);
  2425. X    result = cons( cvflonum(p->z), NIL        );
  2426. X    result = cons( cvflonum(p->y), result    );
  2427. X    result = cons( cvflonum(p->x), result    );
  2428. X    xlpop();
  2429. X    return result;
  2430. X}
  2431. X
  2432. X
  2433. X Minor Observations:
  2434. X -------------------
  2435. X
  2436. Xxlapply, xlevform and sendmsg will issue an error if they encounter a
  2437. Xs_macro CLOSURE.  This is presumably because all macros are expanded
  2438. Xby xleval.c:xlclose when it builds a closure.
  2439. X
  2440. XNeither xlapply nor sendmsg will handle FSUBRs.  This is presumably
  2441. Xa minor bug, left due to the difficulty of keeping arguments
  2442. Xunevaluated to that point. ?
  2443. X
  2444. XSince xlisp tracks the three most recent input expressions (in
  2445. Xvariables +, ++ and +++) and three most recent results (in variables
  2446. X*, ** and ***), things may occasionally not get garbage-collected as
  2447. Xsoon as you expect!
  2448. X
  2449. X
  2450. X
  2451. X Minor Mysteries:
  2452. X ----------------
  2453. X
  2454. XWhy doesn't xlevform trace FSUBRs?  Is this a speed hack?
  2455. X
  2456. XWhy do both xlobj.c:xloinit() and xlobj.c:obsymvols() initialize the
  2457. X"object" and "class" variables?
  2458. END_OF_FILE
  2459. if test 39828 -ne `wc -c <'src/xlisp/xcore/doc/internals.doc'`; then
  2460.     echo shar: \"'src/xlisp/xcore/doc/internals.doc'\" unpacked with wrong size!
  2461. fi
  2462. # end of 'src/xlisp/xcore/doc/internals.doc'
  2463. fi
  2464. echo shar: End of archive 13 \(of 16\).
  2465. cp /dev/null ark13isdone
  2466. MISSING=""
  2467. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
  2468.     if test ! -f ark${I}isdone ; then
  2469.     MISSING="${MISSING} ${I}"
  2470.     fi
  2471. done
  2472. if test "${MISSING}" = "" ; then
  2473.     echo You have unpacked all 16 archives.
  2474.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2475. else
  2476.     echo You still need to unpack the following archives:
  2477.     echo "        " ${MISSING}
  2478. fi
  2479. ##  End of shell archive.
  2480. exit 0
  2481.